monk 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile CHANGED
@@ -1,5 +1,11 @@
1
1
  task :test do
2
- system "cd test && ruby integration_test.rb"
2
+ system "cd test && ruby monk_test.rb"
3
3
  end
4
4
 
5
5
  task :default => :test
6
+
7
+ namespace :test do
8
+ task :integration do
9
+ system "cd test && ruby integration_test.rb"
10
+ end
11
+ end
data/lib/monk.rb CHANGED
@@ -6,25 +6,54 @@ class Monk < Thor
6
6
  include Thor::Actions
7
7
 
8
8
  desc "init", "Initialize a Monk application"
9
- def init(target)
10
- clone(source, target)
11
- cleanup(target)
9
+ method_options(:source => :string)
10
+ def init(target = ".")
11
+ clone(source(options[:source] || "default"), target) ?
12
+ cleanup(target) :
13
+ say_status(:error, clone_error(target))
14
+ end
15
+
16
+ desc "show NAME", "Display the repository address for NAME"
17
+ def show(name)
18
+ say_status name, source(name) || "repository not found"
19
+ end
20
+
21
+ desc "list", "Lists the configured repositories"
22
+ def list
23
+ monk_config.keys.sort.each do |key|
24
+ show(key)
25
+ end
26
+ end
27
+
28
+ desc "add NAME REPOSITORY", "Add the repository to the configuration file"
29
+ def add(name, repository)
30
+ monk_config[name] = repository
31
+ write_monk_config_file
32
+ end
33
+
34
+ desc "rm NAME", "Remove the repository from the configuration file"
35
+ def rm(name)
36
+ monk_config.delete(name)
37
+ write_monk_config_file
12
38
  end
13
39
 
14
40
  private
15
41
 
16
42
  def clone(source, target)
17
- say_status :fetching, source
18
- system "git clone -q --depth 1 #{source} #{target}"
43
+ if Dir["#{target}/*"].empty?
44
+ say_status :fetching, source
45
+ system "git clone -q --depth 1 #{source} #{target}"
46
+ $?.success?
47
+ end
19
48
  end
20
49
 
21
50
  def cleanup(target)
22
51
  inside(target) { remove_file ".git" }
23
- say_status :create, target
52
+ say_status :initialized, target
24
53
  end
25
54
 
26
- def source
27
- monk_config["default"]
55
+ def source(name = "default")
56
+ monk_config[name]
28
57
  end
29
58
 
30
59
  def monk_config_file
@@ -39,8 +68,9 @@ private
39
68
  end
40
69
 
41
70
  def write_monk_config_file
71
+ remove_file monk_config_file
42
72
  create_file monk_config_file do
43
- config = { "default" => "git://github.com/monkrb/skeleton.git" }
73
+ config = @monk_config || { "default" => "git://github.com/monkrb/skeleton.git" }
44
74
  config.to_yaml
45
75
  end
46
76
  end
@@ -48,4 +78,9 @@ private
48
78
  def self.source_root
49
79
  "."
50
80
  end
81
+
82
+ def clone_error(target)
83
+ "Couldn't clone repository into target directory '#{target}'. " +
84
+ "You must have git installed and the target directory must be empty."
85
+ end
51
86
  end
data/monk.gemspec CHANGED
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = "monk"
3
- s.version = "0.0.3"
3
+ s.version = "0.0.4"
4
4
  s.summary = "Monk, the glue framework"
5
5
  s.description = "Monk is a glue framework for web development. It means that instead of installing all the tools you need for your projects, you can rely on a git repository and a list of dependencies, and Monk will care of the rest. By default, it ships with a Sinatra application that includes Contest, Stories, Webrat, Ohm and some other niceties, along with a structure and helpful documentation to get your hands wet in no time."
6
6
  s.authors = ["Damian Janowski", "Michel Martens"]
@@ -11,9 +11,9 @@ Gem::Specification.new do |s|
11
11
 
12
12
  s.executables << "monk"
13
13
 
14
- s.add_dependency("wycats-thor", "~> 0.11")
15
- s.add_dependency("dependencies", ">= 0.0.5")
14
+ s.add_dependency("thor", "~> 0.11")
15
+ s.add_dependency("dependencies", ">= 0.0.6")
16
16
  s.requirements << "git"
17
17
 
18
- s.files = ["LICENSE", "README.markdown", "Rakefile", "bin/monk", "lib/monk.rb", "monk.gemspec", "test/integration_test.rb", "test/sinatra_test.rb"]
18
+ s.files = ["LICENSE", "README.markdown", "Rakefile", "bin/monk", "lib/monk.rb", "monk.gemspec", "test/commands.rb", "test/integration_test.rb", "test/monk_test.rb"]
19
19
  end
data/test/commands.rb ADDED
@@ -0,0 +1,61 @@
1
+ require "open3"
2
+ require "socket"
3
+
4
+ module Test::Commands
5
+ def sh(cmd)
6
+ out, err = nil
7
+
8
+ Open3.popen3(cmd) do |_in, _out, _err|
9
+ out = _out.read
10
+ err = _err.read
11
+ end
12
+
13
+ [out, err]
14
+ end
15
+
16
+ def sh_bg(cmd)
17
+ silence_stream($stdout) do
18
+ silence_stream($stderr) do
19
+ (pid = fork) ? Process.detach(pid) : exec("#{cmd} 2>&1>/dev/null")
20
+ end
21
+ end
22
+ end
23
+
24
+ def listening?(host, port)
25
+ begin
26
+ socket = TCPSocket.new(host, port)
27
+ socket.close unless socket.nil?
28
+ true
29
+ rescue Errno::ECONNREFUSED,
30
+ Errno::EBADF, # Windows
31
+ Errno::EADDRNOTAVAIL # Windows
32
+ false
33
+ end
34
+ end
35
+
36
+ def wait_for_service(host, port, timeout = 3)
37
+ start_time = Time.now
38
+
39
+ until listening?(host, port)
40
+ if timeout && (Time.now > (start_time + timeout))
41
+ raise SocketError.new("Socket #{host}:#{port} did not open within #{timeout} seconds")
42
+ end
43
+ end
44
+
45
+ true
46
+ end
47
+
48
+ def suspects(port)
49
+ list = sh("lsof -i :#{port}").first.split("\n")[1..-1] || []
50
+ list.map {|s| s[/^.+? (\d+)/, 1] }
51
+ end
52
+
53
+ def silence_stream(stream)
54
+ old_stream = stream.dup
55
+ stream.reopen(RUBY_PLATFORM =~ /mswin/ ? 'NUL:' : '/dev/null')
56
+ stream.sync = true
57
+ yield
58
+ ensure
59
+ stream.reopen(old_stream)
60
+ end
61
+ end
@@ -1,29 +1,124 @@
1
1
  require "rubygems"
2
2
  require "contest"
3
- require "open3"
3
+ require "hpricot"
4
4
 
5
- BINARY = File.expand_path(File.join(File.dirname(__FILE__), "..", "bin", "monk"))
5
+ ROOT = File.expand_path(File.join(File.dirname(__FILE__), ".."))
6
+
7
+ $:.unshift ROOT
8
+
9
+ require "test/commands"
6
10
 
7
11
  class TestMonk < Test::Unit::TestCase
8
- context "monk init" do
9
- def monk(args = nil)
10
- out, err = nil
12
+ include Test::Commands
13
+
14
+ def root(*args)
15
+ File.join(ROOT, *args)
16
+ end
17
+
18
+ def monk(args = nil)
19
+ sh("ruby -rubygems #{root "bin/monk"} #{args}")
20
+ end
21
+
22
+ context "monk init NAME" do
23
+ setup do
24
+ @ports_to_close = []
25
+ end
26
+
27
+ def assert_url(url)
28
+ assert_match /200 OK/, sh("curl -I 0.0.0.0:4567#{url}").first.split("\n").first
29
+ end
11
30
 
12
- Open3.popen3("ruby -rubygems #{BINARY} #{args}") do |stdin, stdout, stderr|
13
- out = stdout.read
14
- err = stderr.read
31
+ def try_server(cmd, port)
32
+ binary = cmd[/^(.+?)( |$)/, 1]
33
+
34
+ flunk "Can't find `#{binary}`." unless system("which #{binary} > /dev/null")
35
+
36
+ kill_suspects(port)
37
+ sh_bg(cmd)
38
+
39
+ # Mark the port for closing on teardown, just in case the build fails.
40
+ @ports_to_close << port if wait_for_service("0.0.0.0", port)
41
+
42
+ doc = Hpricot(sh("curl 0.0.0.0:#{port}").first)
43
+
44
+ assert_match /Hello, world/, doc.at("body").inner_text
45
+
46
+ # Make sure all referenced URLs in the layout respond correctly.
47
+ doc.search("//*[@href]").each do |node|
48
+ assert_url node.attributes["href"]
15
49
  end
16
50
 
17
- [out, err]
51
+ doc.search("//*[@src]").each do |node|
52
+ assert_url node.attributes["src"]
53
+ end
18
54
  end
19
55
 
20
56
  should "create a skeleton app with all tests passing" do
21
- Dir.chdir("/tmp") do
57
+ flunk "There is another server running on 0.0.0.0:4567. Suspect PIDs: #{suspects(4567).join(", ")}" if listening?("0.0.0.0", 4567)
58
+ flunk "There is another server running on 0.0.0.0:9292. Suspect PIDs: #{suspects(9292).join(", ")}" if listening?("0.0.0.0", 9292)
59
+
60
+ Dir.chdir(root("test", "tmp")) do
22
61
  FileUtils.rm_rf("monk-test")
23
62
 
24
63
  out, err = monk("init monk-test")
25
- assert out[/create.* monk-test/]
26
- assert !File.directory?("monk-test/.git")
64
+ assert_match /initialized.* monk-test/, out
65
+
66
+ Dir.chdir("monk-test") do
67
+ assert !File.directory?(".git")
68
+
69
+ FileUtils.cp("config/settings.example.yml", "config/settings.yml")
70
+ FileUtils.cp("config/redis/development.example.conf", "config/redis/development.conf")
71
+ FileUtils.cp("config/redis/test.example.conf", "config/redis/test.conf")
72
+
73
+ # Load Redis.
74
+ sh "redis-server config/redis/test.conf"
75
+ wait_for_service("0.0.0.0", 6380)
76
+
77
+ sh "redis-server config/redis/development.conf"
78
+ wait_for_service("0.0.0.0", 6379)
79
+
80
+ assert sh("rake"), "the build didn't pass."
81
+ assert sh("rake1.9"), "the build didn't pass under Ruby 1.9."
82
+
83
+ try_server "ruby init.rb", 4567
84
+ try_reloading
85
+ try_server "rackup", 9292
86
+
87
+ try_server "ruby1.9 init.rb", 4567
88
+ try_reloading
89
+ try_server "rackup1.9", 9292
90
+ end
91
+ end
92
+ end
93
+
94
+ def try_reloading
95
+ gsub_file("app/routes/home.rb", "haml :home", "'Goodbye'") do
96
+ sleep 0.2
97
+ assert_match /Goodbye/, sh("curl 0.0.0.0:4567").first
98
+ end
99
+ end
100
+
101
+ def gsub_file(file, *args)
102
+ old = File.read(file)
103
+
104
+ begin
105
+ new = old.gsub(*args)
106
+ File.open(file, "w") {|f| f.write(new) }
107
+ yield
108
+ ensure
109
+ File.open(file, "w") {|f| f.write(old) }
110
+ end
111
+ end
112
+
113
+ def kill_suspects(port)
114
+ list = suspects(port)
115
+
116
+ sh "kill -9 #{list.join(" ")}" unless list.empty?
117
+ end
118
+
119
+ teardown do
120
+ @ports_to_close.each do |port|
121
+ kill_suspects port
27
122
  end
28
123
  end
29
124
  end
data/test/monk_test.rb ADDED
@@ -0,0 +1,127 @@
1
+ require "rubygems"
2
+ require "contest"
3
+ require "hpricot"
4
+
5
+ ROOT = File.expand_path(File.join(File.dirname(__FILE__), ".."))
6
+
7
+ $:.unshift ROOT
8
+
9
+ require "test/commands"
10
+
11
+ class TestMonk < Test::Unit::TestCase
12
+ include Test::Commands
13
+
14
+ def root(*args)
15
+ File.join(ROOT, *args)
16
+ end
17
+
18
+ def monk(args = nil)
19
+ sh("ruby -rubygems #{root "bin/monk"} #{args}")
20
+ end
21
+
22
+ context "monk init NAME" do
23
+ should "fail if the target working directory is not empty" do
24
+ Dir.chdir(root("test", "tmp")) do
25
+ FileUtils.rm_rf("monk-test")
26
+ FileUtils.mkdir("monk-test")
27
+
28
+ Dir.chdir("monk-test") do
29
+ FileUtils.touch("foobar")
30
+ end
31
+
32
+ out, err = monk("init monk-test")
33
+ assert_match /error/, out
34
+ end
35
+ end
36
+
37
+ should "create a skeleton app in the target directory" do
38
+ Dir.chdir(root("test", "tmp")) do
39
+ FileUtils.rm_rf("monk-test")
40
+
41
+ out, err = monk("init monk-test")
42
+ assert_match /initialized.* monk-test/, out
43
+ end
44
+ end
45
+ end
46
+
47
+ context "monk init" do
48
+ should "fail if the current working directory is not empty" do
49
+ Dir.chdir(root("test", "tmp")) do
50
+ FileUtils.rm_rf("monk-test")
51
+ FileUtils.mkdir("monk-test")
52
+
53
+
54
+ Dir.chdir("monk-test") do
55
+ FileUtils.touch("foobar")
56
+ out, err = monk("init")
57
+ assert_match /error/, out
58
+ end
59
+ end
60
+ end
61
+
62
+ should "create a skeleton app in the working directory" do
63
+ Dir.chdir(root("test", "tmp")) do
64
+ FileUtils.rm_rf("monk-test")
65
+ FileUtils.mkdir("monk-test")
66
+
67
+ Dir.chdir("monk-test") do
68
+ out, err = monk("init")
69
+ assert_match /initialized/, out
70
+ end
71
+ end
72
+ end
73
+
74
+ should "use an alternative skeleton if the option is provided" do
75
+ Dir.chdir(root("test", "tmp")) do
76
+ FileUtils.rm_rf("monk-test")
77
+ FileUtils.mkdir("monk-test")
78
+
79
+ monk("add foobar git://github.com/monkrb/skeleton.git")
80
+
81
+ Dir.chdir("monk-test") do
82
+ out, err = monk("init -s foo")
83
+ assert_match /initialized/, out
84
+ end
85
+ end
86
+ end
87
+ end
88
+
89
+ context "monk show NAME" do
90
+ should "display the repository for NAME" do
91
+ out, err = monk("show default")
92
+ assert out["git://github.com/monkrb/skeleton.git"]
93
+ end
94
+
95
+ should "display nothing if NAME is not set" do
96
+ out, err = monk("show foobar")
97
+ assert out["repository not found"]
98
+ end
99
+ end
100
+
101
+ context "monk list" do
102
+ should "display the configured repositories" do
103
+ out, err = monk("list")
104
+ assert out["default"]
105
+ assert out["git://github.com/monkrb/skeleton.git"]
106
+ end
107
+ end
108
+
109
+ context "monk add NAME REPOSITORY" do
110
+ should "add the named repository to the configuration" do
111
+ monk("add foobar git://github.com/monkrb/foo.git")
112
+ out, err = monk("show foobar")
113
+ assert out["foobar"]
114
+ assert out["git://github.com/monkrb/foo.git"]
115
+ monk("rm foobar")
116
+ end
117
+ end
118
+
119
+ context "monk rm NAME" do
120
+ should "remove the named repository from the configuration" do
121
+ monk("add foobar git://github.com/monkrb/foo.git")
122
+ monk("rm foobar")
123
+ out, err = monk("show foobar")
124
+ assert out["repository not found"]
125
+ end
126
+ end
127
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: monk
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Damian Janowski
@@ -10,11 +10,11 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2009-07-23 00:00:00 -03:00
13
+ date: 2009-08-07 00:00:00 -03:00
14
14
  default_executable:
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
- name: wycats-thor
17
+ name: thor
18
18
  type: :runtime
19
19
  version_requirement:
20
20
  version_requirements: !ruby/object:Gem::Requirement
@@ -31,7 +31,7 @@ dependencies:
31
31
  requirements:
32
32
  - - ">="
33
33
  - !ruby/object:Gem::Version
34
- version: 0.0.5
34
+ version: 0.0.6
35
35
  version:
36
36
  description: Monk is a glue framework for web development. It means that instead of installing all the tools you need for your projects, you can rely on a git repository and a list of dependencies, and Monk will care of the rest. By default, it ships with a Sinatra application that includes Contest, Stories, Webrat, Ohm and some other niceties, along with a structure and helpful documentation to get your hands wet in no time.
37
37
  email:
@@ -50,8 +50,9 @@ files:
50
50
  - bin/monk
51
51
  - lib/monk.rb
52
52
  - monk.gemspec
53
+ - test/commands.rb
53
54
  - test/integration_test.rb
54
- - test/sinatra_test.rb
55
+ - test/monk_test.rb
55
56
  has_rdoc: true
56
57
  homepage: http://monkrb.com
57
58
  licenses: []
data/test/sinatra_test.rb DELETED
@@ -1,13 +0,0 @@
1
- require File.dirname(__FILE__) + '/helper'
2
-
3
- class SinatraTest < Test::Unit::TestCase
4
- it 'creates a new Sinatra::Base subclass on new' do
5
- app =
6
- Sinatra.new do
7
- get '/' do
8
- 'Hello World'
9
- end
10
- end
11
- assert_same Sinatra::Base, app.superclass
12
- end
13
- end