monk 0.0.3 → 0.0.4

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