dreamcatch 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,25 @@
1
+ ## MAC OS
2
+ .DS_Store
3
+
4
+ ## TEXTMATE
5
+ *.tmproj
6
+ tmtags
7
+
8
+ ## EMACS
9
+ *~
10
+ \#*
11
+ .\#*
12
+
13
+ ## VIM
14
+ *.swp
15
+
16
+ ## PROJECT::GENERAL
17
+ coverage
18
+ rdoc
19
+ pkg
20
+ integration
21
+ integration_test
22
+ integration_test/
23
+ integration_test/*
24
+ .document
25
+ ## PROJECT::SPECIFIC
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Fernando Barajas
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.
@@ -0,0 +1,64 @@
1
+ = Dreamcatch
2
+
3
+ A Ruby Gem to create new git repositories on dreamhost using WebDav
4
+
5
+
6
+ Dreamcatch::Config.remote_url = "repo.example.com/git"
7
+ Dreamcatch::Config.username = "username"
8
+ Dreamcatch::Config.password = "password"
9
+
10
+
11
+ repo = Dreamcatch::Repo.new(
12
+ :dir => "~/some/dir",
13
+ :name => "repo.git"
14
+ )
15
+ repo.save # => returns true when save success
16
+
17
+
18
+ repo = Dreamcatch::Repo.new(
19
+ :dir => "~/some/dir",
20
+ :name => "repo.git"
21
+ )
22
+ repo.delete # => returns true when delete is success
23
+
24
+
25
+ repo = Dreamcatch::Repo.new(
26
+ :dir => "~/some/dir",
27
+ :name => "repo.git"
28
+ )
29
+ repo.rename("new-name.git") # => returns true when rename was success
30
+
31
+
32
+ repo = Dreamcatch::Repo.new(
33
+ :dir => "~/some/dir",
34
+ :name => "repo.git"
35
+ )
36
+ repo.delete_local # => returns true when rename was success
37
+
38
+
39
+ repo = Dreamcatch::Repo.new(
40
+ :dir => "~/some/dir",
41
+ :name => "repo.git"
42
+ )
43
+ repo.errors # => returns an array of errors if any where found after delete, delete_local, rename or save
44
+
45
+
46
+ == Gem Dependencies
47
+
48
+ * *grit* must also be available
49
+
50
+ sudo gem install grit
51
+
52
+
53
+ == Note on Patches/Pull Requests
54
+
55
+ * Fork the project.
56
+ * Make your feature addition or bug fix.
57
+ * Add tests for it. This is important so I don't break it in a
58
+ future version unintentionally.
59
+ * Commit, do not mess with rakefile, version, or history.
60
+ * Send me a pull request.
61
+
62
+ == Copyright
63
+
64
+ Copyright (c) 2009 Fernando Barajas. See LICENSE for details.
@@ -0,0 +1,47 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "dreamcatch"
8
+ gem.summary = %Q{Git on Dreamhost WebDAV}
9
+ gem.description = %Q{A simple way to add and remove git repos on dreamhost webdav}
10
+ gem.email = "fernyb@fernyb.net"
11
+ gem.homepage = "http://github.com/fernyb/dreamcatch"
12
+ gem.authors = ["Fernando Barajas"]
13
+ gem.add_development_dependency "rspec", ">= 1.2.9"
14
+ gem.add_dependency "grit"
15
+
16
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
17
+ end
18
+ rescue LoadError
19
+ puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
20
+ end
21
+
22
+ require 'spec/rake/spectask'
23
+ Spec::Rake::SpecTask.new(:spec) do |spec|
24
+ spec.libs << 'lib' << 'spec'
25
+ spec.spec_files = FileList['spec/**/*_spec.rb']
26
+ end
27
+
28
+ Spec::Rake::SpecTask.new(:rcov) do |spec|
29
+ spec.libs << 'lib' << 'spec'
30
+ spec.pattern = 'spec/**/*_spec.rb'
31
+ spec.rcov = true
32
+ spec.rcov_opts = ['--exclude', "/Library/Ruby/Gems,_spec.rb,spec_helper.rb"]
33
+ end
34
+
35
+ task :spec => :check_dependencies
36
+
37
+ task :default => :spec
38
+
39
+ require 'rake/rdoctask'
40
+ Rake::RDocTask.new do |rdoc|
41
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
42
+
43
+ rdoc.rdoc_dir = 'rdoc'
44
+ rdoc.title = "dreamcatch #{version}"
45
+ rdoc.rdoc_files.include('README*')
46
+ rdoc.rdoc_files.include('lib/**/*.rb')
47
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.1
@@ -0,0 +1,75 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{dreamcatch}
8
+ s.version = "0.0.1"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Fernando Barajas"]
12
+ s.date = %q{2009-11-27}
13
+ s.description = %q{A simple way to add and remove git repos on dreamhost webdav}
14
+ s.email = %q{fernyb@fernyb.net}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE",
17
+ "README.rdoc"
18
+ ]
19
+ s.files = [
20
+ ".gitignore",
21
+ "LICENSE",
22
+ "README.rdoc",
23
+ "Rakefile",
24
+ "VERSION",
25
+ "dreamcatch.gemspec",
26
+ "lib/dreamcatch.rb",
27
+ "lib/dreamcatch/config.rb",
28
+ "lib/dreamcatch/dav.rb",
29
+ "lib/dreamcatch/dav_response.rb",
30
+ "lib/dreamcatch/error.rb",
31
+ "lib/dreamcatch/repo.rb",
32
+ "lib/dreamcatch/web_dav.rb",
33
+ "spec/dreamcatch/config_spec.rb",
34
+ "spec/dreamcatch/dav_response_spec.rb",
35
+ "spec/dreamcatch/dav_spec.rb",
36
+ "spec/dreamcatch/error_spec.rb",
37
+ "spec/dreamcatch/repo_spec.rb",
38
+ "spec/fixtures/response/404_not_found.txt",
39
+ "spec/fixtures/response/put.txt",
40
+ "spec/fixtures/response/put_no_body.txt",
41
+ "spec/fixtures/response/put_two.txt",
42
+ "spec/spec.opts",
43
+ "spec/spec_helper.rb"
44
+ ]
45
+ s.homepage = %q{http://github.com/fernyb/dreamcatch}
46
+ s.rdoc_options = ["--charset=UTF-8"]
47
+ s.require_paths = ["lib"]
48
+ s.rubygems_version = %q{1.3.5}
49
+ s.summary = %q{Git on Dreamhost WebDAV}
50
+ s.test_files = [
51
+ "spec/dreamcatch/config_spec.rb",
52
+ "spec/dreamcatch/dav_response_spec.rb",
53
+ "spec/dreamcatch/dav_spec.rb",
54
+ "spec/dreamcatch/error_spec.rb",
55
+ "spec/dreamcatch/repo_spec.rb",
56
+ "spec/spec_helper.rb"
57
+ ]
58
+
59
+ if s.respond_to? :specification_version then
60
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
61
+ s.specification_version = 3
62
+
63
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
64
+ s.add_development_dependency(%q<rspec>, [">= 1.2.9"])
65
+ s.add_runtime_dependency(%q<grit>, [">= 0"])
66
+ else
67
+ s.add_dependency(%q<rspec>, [">= 1.2.9"])
68
+ s.add_dependency(%q<grit>, [">= 0"])
69
+ end
70
+ else
71
+ s.add_dependency(%q<rspec>, [">= 1.2.9"])
72
+ s.add_dependency(%q<grit>, [">= 0"])
73
+ end
74
+ end
75
+
@@ -0,0 +1,11 @@
1
+ require File.dirname(__FILE__) + "/dreamcatch/config"
2
+ require File.dirname(__FILE__) + "/dreamcatch/dav"
3
+ require File.dirname(__FILE__) + "/dreamcatch/dav_response"
4
+ require File.dirname(__FILE__) + "/dreamcatch/web_dav"
5
+ require File.dirname(__FILE__) + "/dreamcatch/repo"
6
+ require File.dirname(__FILE__) + "/dreamcatch/error"
7
+
8
+ require "rubygems"
9
+ require "grit"
10
+ require "open3"
11
+ require "base64"
@@ -0,0 +1,17 @@
1
+ module Dreamcatch
2
+ class Config
3
+ class << self
4
+ attr_accessor :remote_url
5
+ attr_accessor :username
6
+ attr_accessor :password
7
+
8
+ def remote_url
9
+ "http://#{@remote_url}"
10
+ end
11
+
12
+ def credentials
13
+ Base64.encode64("#{@username}:#{@password}").gsub(/\n+/, "")
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,126 @@
1
+ #
2
+ # This class should replace fernyb_davclient which is a total mess
3
+ #
4
+ module Dreamcatch
5
+ class DAV
6
+ attr_accessor :notifier
7
+
8
+ def exists?(remote_file_name)
9
+ resp = run("#{remote_file_name}")
10
+ puts "* Exists : #{resp.status_code} #{resp.status}\n" if $DEBUG
11
+ if resp.status_code == 404
12
+ false
13
+ elsif resp.status_code == 200
14
+ true
15
+ else
16
+ nil
17
+ end
18
+ end
19
+
20
+ def delete(remote_file)
21
+ command = []
22
+ command << "--request DELETE"
23
+ command << %Q{--header 'Content-Type: text/xml; charset="utf-8"'}
24
+ command << remote_file
25
+ curl_command = command.join(" ")
26
+ resp = run(curl_command)
27
+
28
+ puts "* DELETE: #{resp.status_code} #{resp.status}" if $DEBUG
29
+
30
+ if resp.status_code == 401
31
+ @notifier.add_error Dreamcatch::Error.new("#{resp.status_code} #{resp.status}")
32
+ false
33
+ elsif resp.status_code == 204
34
+ resp
35
+ else
36
+ @notifier.add_error Dreamcatch::Error.new("#{resp.status_code} #{resp.status}")
37
+ false
38
+ end
39
+ end
40
+
41
+ def rename(current_name, new_name)
42
+ command = []
43
+ command << "--request MOVE"
44
+ command << %Q{--header 'Content-Type: text/xml; charset="utf-8"'}
45
+ command << %Q{--header 'Destination: #{new_name}'}
46
+ curl_command = command.join(" ") + " " + current_name
47
+ resp = run(curl_command)
48
+ puts "* MOVE: #{resp.status_code} #{resp.status}" if $DEBUG
49
+
50
+ if resp.status_code == 201
51
+ resp
52
+ else
53
+ @notifier.add_error Dreamcatch::Error.new("#{resp.status_code} #{resp.status}")
54
+ false
55
+ end
56
+ end
57
+
58
+ def put(remote_file_name, local_file_name)
59
+ command = []
60
+ command << "--upload-file #{local_file_name} #{remote_file_name}"
61
+ curl_command = command.join(" ")
62
+ resp = run(curl_command)
63
+ puts "* PUT: #{resp.status_code} #{resp.status}" if $DEBUG
64
+ if resp.status_code == 201
65
+ resp
66
+ else
67
+ @notifier.add_error Dreamcatch::Error.new("#{resp.status_code} #{resp.status}")
68
+ false
69
+ end
70
+ end
71
+
72
+ def mkcol(remote_url)
73
+ curl_command = []
74
+ curl_command << "--request MKCOL"
75
+ curl_command << %Q{--header 'Content-Type: text/xml; charset="utf-8"'}
76
+ curl_command = curl_command.join(" ") + " " + remote_url
77
+ resp = run(curl_command)
78
+ puts "* MKCOL #{resp.status_code} #{resp.status}" if $DEBUG
79
+ if resp.status_code == 201
80
+ resp
81
+ else
82
+ @notifier.add_error Dreamcatch::Error.new("#{resp.status_code} #{resp.status}")
83
+ false
84
+ end
85
+ end
86
+
87
+ def run(command)
88
+ options = []
89
+ options << "--include"
90
+ options << "--location"
91
+ options << %Q{--header 'Authorization: Basic #{Dreamcatch::Config.credentials}'}
92
+ options = options.join(" ")
93
+ response = nil
94
+
95
+ curl_command = "curl #{options} #{command}"
96
+ puts "\n*** #{curl_command}\n" if $DEBUG
97
+
98
+ stdin, stdout, stderr = Open3.popen3(curl_command)
99
+ response = stdout.readlines.join("")
100
+
101
+ response = headers_and_response_from_response(response)
102
+ end
103
+
104
+ def headers_and_response_from_response(response)
105
+ head = response.to_s.scan(/HTTP\/(\d+.\d+) (\d+) (.*)\r/)
106
+ resp = Dreamcatch::DAVResponse.new
107
+ if head.size == 1
108
+ resp.status = head.first[2]
109
+ resp.status_code = head.first[1].to_i
110
+ elsif head.size >= 2
111
+ resp.status = head.last[2]
112
+ resp.status_code = head.last[1].to_i
113
+ end
114
+
115
+ body = response.to_s.split("\r\n\r\n")
116
+ if body.last.to_s.match(/^HTTP\/(\d+).(\d+)/)
117
+ resp.head = body.last
118
+ resp.body = nil
119
+ else
120
+ resp.head = body[(body.size - 2)]
121
+ resp.body = body.last
122
+ end
123
+ resp
124
+ end
125
+ end
126
+ end
@@ -0,0 +1,8 @@
1
+ module Dreamcatch
2
+ class DAVResponse
3
+ attr_accessor :status
4
+ attr_accessor :status_code
5
+ attr_accessor :head
6
+ attr_accessor :body
7
+ end
8
+ end
@@ -0,0 +1,13 @@
1
+ module Dreamcatch
2
+ class Error
3
+ attr_accessor :description
4
+
5
+ def initialize(msg)
6
+ @description = msg
7
+ end
8
+
9
+ def to_s
10
+ @description
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,89 @@
1
+ module Dreamcatch
2
+ class Invalid < StandardError; end
3
+
4
+ class Repo
5
+ attr_reader :webdav
6
+ attr_reader :errors
7
+
8
+ def initialize(opts={})
9
+ @errors ||= []
10
+ @name = opts[:name]
11
+ @dir = opts[:dir]
12
+ raise Dreamcatch::Invalid.new("Repo must have name") if @name.nil?
13
+ raise Dreamcatch::Invalid.new("Repo must have dir") if @dir.nil?
14
+ @webdav = Dreamcatch::WebDav.new(Dreamcatch::Config.remote_url, self)
15
+ end
16
+
17
+ def delete
18
+ if webdav.exists?("#{@name}")
19
+ webdav.delete("#{@name}")
20
+ else
21
+ self.add_error Dreamcatch::Error.new(%Q{#{@name} does not exists})
22
+ nil
23
+ end
24
+ end
25
+
26
+ def delete_local
27
+ if local_repo_exists?
28
+ if FileUtils.remove_dir(local_repo) == 0
29
+ true
30
+ else
31
+ self.add_error(Dreamcatch::Error.new(%Q{#{local_repo} could not be removed}))
32
+ nil
33
+ end
34
+ else
35
+ self.add_error Dreamcatch::Error.new(%Q{#{local_repo} does not exist locally})
36
+ nil
37
+ end
38
+ end
39
+
40
+ def rename(new_name)
41
+ if webdav.exists?("#{@name}")
42
+ if !webdav.exists?("#{new_name}")
43
+ webdav.rename(@name, new_name)
44
+ else
45
+ self.add_error Dreamcatch::Error.new(%Q{#{new_name} already exists})
46
+ nil
47
+ end
48
+ else
49
+ self.add_error Dreamcatch::Error.new(%Q{#{@name} does not exist})
50
+ nil
51
+ end
52
+ end
53
+
54
+ def save
55
+ if local_repo_exists?
56
+ upload_to_webdav(@dir, @name)
57
+ elsif init_bare(local_repo)
58
+ upload_to_webdav(@dir, @name)
59
+ end
60
+ end
61
+
62
+ def local_repo
63
+ "#{@dir}/#{@name}"
64
+ end
65
+
66
+ def local_repo_exists?
67
+ File.exists? local_repo
68
+ end
69
+
70
+ def upload_to_webdav(local_dir, repo_name)
71
+ webdav.put(local_dir, repo_name)
72
+ end
73
+
74
+ def init_bare(local_repo_path)
75
+ Grit::Repo.init_bare(local_repo_path)
76
+ end
77
+
78
+ def errors
79
+ @errors
80
+ end
81
+
82
+ def errors=(message)
83
+ @errors ||= []
84
+ @errors << message if message.kind_of?(Dreamcatch::Error)
85
+ end
86
+ alias_method :add_error, :errors=
87
+ end
88
+
89
+ end
@@ -0,0 +1,57 @@
1
+ module Dreamcatch
2
+ class WebDav
3
+ attr_reader :remote_url
4
+ attr_accessor :notifier
5
+ attr_accessor :webdav
6
+
7
+ def initialize(url, notify=nil)
8
+ @remote_url = url
9
+ @webdav ||= Dreamcatch::DAV.new
10
+ @webdav.notifier = notify
11
+ @notifier = notify
12
+ end
13
+
14
+ def exists?(save_name)
15
+ save_name << "/" if save_name.match(/\.git$/)
16
+ webdav.exists?("#{remote_url}/#{save_name}")
17
+ end
18
+
19
+ def delete(repo_name)
20
+ webdav.delete("#{remote_url}/#{repo_name}/")
21
+ end
22
+
23
+ def rename(name, new_name)
24
+ unless webdav.exists?("#{remote_url}/#{new_name}")
25
+ webdav.rename("#{remote_url}/#{name}", "#{remote_url}/#{new_name}")
26
+ else
27
+ @notifier.add_error Dreamcatch::Error.new(%Q{#{new_name} does not exists})
28
+ end
29
+ end
30
+
31
+ def put(local_dir, save_name)
32
+ if exists?("#{save_name}")
33
+ @notifier.add_error Dreamcatch::Error.new(%Q{#{save_name} already exists})
34
+ return nil
35
+ elsif File.directory?("#{local_dir}/#{save_name}")
36
+ recursive_put(local_dir, save_name)
37
+ elsif !File.directory?("#{local_dir}/#{save_name}")
38
+ webdav.put("#{remote_url}/#{save_name}", "#{local_dir}/#{save_name}")
39
+ end
40
+ end
41
+
42
+ def recursive_put(local_dir, save_name)
43
+ if webdav.mkcol("#{remote_url}/#{save_name}")
44
+ results = Dir["#{local_dir}/#{save_name}/**/*"].collect do |local_file|
45
+ base_file_name = local_file.split("#{local_dir}")
46
+ if File.directory?(local_file)
47
+ webdav.mkcol("#{remote_url}#{base_file_name}")
48
+ else
49
+ webdav.put("#{remote_url}#{base_file_name}", "#{local_dir}#{base_file_name}")
50
+ end
51
+ end.select {|status| status == false || status.nil? }
52
+ results.include?(false) == false
53
+ end
54
+ end
55
+
56
+ end
57
+ end
@@ -0,0 +1,48 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe Dreamcatch::Config do
4
+ describe :accessors do
5
+ it "has username accessor" do
6
+ Dreamcatch::Config.should respond_to(:username)
7
+ end
8
+
9
+ it "has password accessor" do
10
+ Dreamcatch::Config.should respond_to(:password)
11
+ end
12
+
13
+ it "has remote_url accessor" do
14
+ Dreamcatch::Config.should respond_to(:remote_url)
15
+ end
16
+ end
17
+
18
+ describe :remote_url do
19
+ it "returns url with http prefix" do
20
+ Dreamcatch::Config.username = nil
21
+ Dreamcatch::Config.password = nil
22
+ Dreamcatch::Config.remote_url = "repo.example.com/git"
23
+ Dreamcatch::Config.remote_url.should == "http://repo.example.com/git"
24
+ end
25
+ end
26
+
27
+ describe :credentials do
28
+ it "returns credentials base64 encoded" do
29
+ Dreamcatch::Config.username = "username"
30
+ Dreamcatch::Config.password = "password"
31
+ Dreamcatch::Config.credentials.should == "dXNlcm5hbWU6cGFzc3dvcmQ="
32
+ end
33
+
34
+ it "credentials should not be username:password" do
35
+ Dreamcatch::Config.username = "john"
36
+ Dreamcatch::Config.password = "doe"
37
+ Dreamcatch::Config.credentials.should_not == "dXNlcm5hbWU6cGFzc3dvcmQ="
38
+ end
39
+
40
+ it "should base64 encode username and password" do
41
+ Dreamcatch::Config.username = "username"
42
+ Dreamcatch::Config.password = "password"
43
+
44
+ Base64.should_receive(:encode64).with("username:password").and_return "username:password"
45
+ Dreamcatch::Config.credentials
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,23 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe Dreamcatch::DAVResponse do
4
+ before :each do
5
+ @response = Dreamcatch::DAVResponse.new
6
+ end
7
+
8
+ it "has status attribute" do
9
+ @response.should respond_to(:status)
10
+ end
11
+
12
+ it "has status_code attribute" do
13
+ @response.should respond_to(:status_code)
14
+ end
15
+
16
+ it "has head attribute" do
17
+ @response.should respond_to(:head)
18
+ end
19
+
20
+ it "has body attribute" do
21
+ @response.should respond_to(:body)
22
+ end
23
+ end
@@ -0,0 +1,202 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe "Dreamcatch::DAV" do
4
+ before :each do
5
+ @dav = Dreamcatch::DAV.new
6
+ @dav.notifier = mock("Notifier", :errors => [], :add_error => nil)
7
+ end
8
+
9
+ describe :headers_and_response_from_response do
10
+ describe :put do
11
+ before :each do
12
+ dav = Dreamcatch::DAV.new
13
+ @resp = dav.send(:headers_and_response_from_response, response_for("put"))
14
+ @resp_two = dav.send(:headers_and_response_from_response, response_for("put_two"))
15
+ @resp_three = dav.send(:headers_and_response_from_response, response_for("put_no_body"))
16
+ end
17
+
18
+ it "should return Dreamcatch::Response" do
19
+ [@resp, @resp_two, @resp_three].each {|rp| rp.should be_kind_of(Dreamcatch::DAVResponse) }
20
+ end
21
+
22
+ it "should have status code 201 Created" do
23
+ [@resp, @resp_two, @resp_three].each {|rp| rp.status_code.should == 201 }
24
+ end
25
+
26
+ it "should have status" do
27
+ [@resp, @resp_two, @resp_three].each {|rp| rp.status.should == "Created" }
28
+ end
29
+
30
+ it "should have http headers" do
31
+ [@resp, @resp_two, @resp_three].each do |rp|
32
+ rp.head.should == "HTTP/1.1 201 Created\r\nDate: Sat, 21 Nov 2009 15:21:40 GMT\r\nServer: Apache\r\nLocation: http://example.com/git/test.txt\r\nVary: Accept-Encoding\r\nMS-Author-Via: DAV\r\nContent-Length: 185\r\nContent-Type: text/html; charset=ISO-8859-1"
33
+ end
34
+ end
35
+
36
+ it "should have body" do
37
+ [@resp, @resp_two].each do |rp|
38
+ rp.body.should == "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\r\n<html><head>\r\n<title>201 Created</title>\r\n</head><body>\r\n<h1>Created</h1>\r\n<p>Resource /git/test.txt has been created.</p>\r\n</body></html>\r\n"
39
+ end
40
+ end
41
+
42
+ it "body should be nil" do
43
+ @resp_three.body.should be_nil
44
+ end
45
+ end # => end put
46
+ end
47
+
48
+ describe :mkcol do
49
+ it "should execute correct command" do
50
+ response = mock("Response", :status_code => 201)
51
+ @dav.should_receive(:run).with(%Q{--request MKCOL --header 'Content-Type: text/xml; charset="utf-8"' http://example.com/git/repo.git}).and_return(response)
52
+ @dav.mkcol("http://example.com/git/repo.git")
53
+ end
54
+
55
+ it "should return response when status_code is 201" do
56
+ response = mock("Response", :status_code => 201)
57
+ @dav.stub!(:run).and_return(response)
58
+ @dav.mkcol("http://example.com/git/repo.git").should == response
59
+ end
60
+
61
+ it "should return false when status_code is not 201" do
62
+ response = mock("Response", :status_code => 500, :status => "Failure")
63
+ @dav.stub!(:run).and_return(response)
64
+ @dav.mkcol("http://example.com/git/repo.git").should be_false
65
+ end
66
+ end
67
+
68
+ describe :put do
69
+ it "should execute correct command" do
70
+ response = mock("Response", :status_code => 201)
71
+ @dav.should_receive(:run).with("--upload-file /Users/fernyb/rails/local_file.txt http://example.com/git/file.txt").and_return(response)
72
+ @dav.put("http://example.com/git/file.txt", "/Users/fernyb/rails/local_file.txt")
73
+ end
74
+
75
+ it "should return response object when status code is 201" do
76
+ response = mock("Response", :status_code => 201)
77
+ @dav.stub!(:run).and_return(response)
78
+ @dav.put("http://example.com/git/file.txt", "/Users/fernyb/rails/local_file.txt").should == response
79
+ end
80
+
81
+ it "should return response object when status code is 201" do
82
+ response = mock("Response", :status_code => 500, :status => "Failure")
83
+ @dav.stub!(:run).and_return(response)
84
+ @dav.put("http://example.com/git/file.txt", "/Users/fernyb/rails/local_file.txt").should be_false
85
+ end
86
+ end
87
+
88
+ describe :exists? do
89
+ it "should execute correct command" do
90
+ response = mock("Response", :status_code => 200)
91
+ dav = Dreamcatch::DAV.new
92
+ dav.should_receive(:run).with("http://example.com/git/file.txt").and_return(response)
93
+ dav.exists?("http://example.com/git/file.txt")
94
+ end
95
+
96
+ it "returns false when status_code is 404" do
97
+ response = mock("Response", :status_code => 404)
98
+ dav = Dreamcatch::DAV.new
99
+ dav.stub!(:run).and_return(response)
100
+ dav.exists?("http://example.com/git/file.txt").should be_false
101
+ end
102
+
103
+ it "returns true when status_code is 200" do
104
+ response = mock("Response", :status_code => 200)
105
+ dav = Dreamcatch::DAV.new
106
+ dav.stub!(:run).and_return(response)
107
+ dav.exists?("http://example.com/git/file.txt").should be_true
108
+ end
109
+
110
+ it "returns nil when status_code is not 200 or 404" do
111
+ response = mock("Response", :status_code => 500)
112
+ dav = Dreamcatch::DAV.new
113
+ dav.stub!(:run).and_return(response)
114
+ dav.exists?("http://example.com/git/file.txt").should be_nil
115
+ end
116
+ end
117
+
118
+ describe :run do
119
+ it "should execute curl command" do
120
+ stdin, stdout, stderr = mock("StdIn"), mock("StdOut"), mock("StdErr")
121
+ stdout = response_for_into_array("put")
122
+
123
+ Open3.should_receive(:popen3).with("curl --include --location --header 'Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=' http://example.com/git/file.txt").and_return([stdin, stdout, stderr])
124
+ @dav.send(:run, "http://example.com/git/file.txt")
125
+ end
126
+
127
+ it "should return Dreamcatch::DAVResponse object" do
128
+ stdin, stdout, stderr = mock("StdIn"), mock("StdOut"), mock("StdErr")
129
+ stdout = response_for_into_array("put")
130
+
131
+ Open3.should_receive(:popen3).with("curl --include --location --header 'Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=' --request MKCOL http://example.com/git/collection").and_return([stdin, stdout, stderr])
132
+ @dav.send(:run, "--request MKCOL http://example.com/git/collection").should be_kind_of(Dreamcatch::DAVResponse)
133
+ end
134
+
135
+ it "should parse the http response" do
136
+ stdin, stdout, stderr = mock("StdIn"), mock("StdOut"), mock("StdErr")
137
+ stdout = response_for_into_array("put")
138
+ response = stdout.readlines.join("")
139
+ stdout.rewind
140
+
141
+ Open3.stub!(:popen3).and_return([stdin, stdout, stderr])
142
+ @dav.should_receive(:headers_and_response_from_response).with(response)
143
+ @dav.send(:run, "--request MKCOL http://example.com/git/collection")
144
+ end
145
+ end
146
+
147
+ describe :delete do
148
+ it "should execute correct command" do
149
+ resp = mock("Response", :status_code => 204)
150
+ @dav.should_receive(:run).with(%Q{--request DELETE --header 'Content-Type: text/xml; charset="utf-8"' http://example.com/git/file.txt}).and_return(resp)
151
+ @dav.delete("http://example.com/git/file.txt")
152
+ end
153
+
154
+ it "should return Response when status_code is 204" do
155
+ resp = mock("Response", :status_code => 204)
156
+ @dav.stub!(:run).and_return resp
157
+ @dav.delete("http://example.com/git/file.txt").should == resp
158
+ end
159
+
160
+ it "should not return Response when status code is not 201" do
161
+ resp = mock("Response", :status_code => 500, :status => "Failure")
162
+ @dav.stub!(:run).and_return resp
163
+ @dav.delete("http://example.com/git/file.txt").should_not == resp
164
+ end
165
+
166
+ it "should return false when status_code is not 201" do
167
+ resp = mock("Response", :status_code => 500, :status => "Failure")
168
+ @dav.stub!(:run).and_return resp
169
+ @dav.delete("http://example.com/git/file.txt").should be_false
170
+ end
171
+
172
+ it "should return false when status_code is 401" do
173
+ resp = mock("Response", :status_code => 401, :status => "Four Oh Four")
174
+ @dav.stub!(:run).and_return resp
175
+ @dav.delete("http://example.com/git/file.txt").should be_false
176
+ end
177
+ end
178
+
179
+ describe :rename do
180
+ before :each do
181
+ Dreamcatch::Config.stub!(:credentials).and_return "username:password"
182
+ end
183
+
184
+ it "should execute correct command" do
185
+ resp = mock("Response", :status_code => 201)
186
+ @dav.should_receive(:run).with(%Q{--request MOVE --header 'Content-Type: text/xml; charset=\"utf-8\"' --header 'Destination: http://example.com/git/new_name.git' http://example.com/git/name.git}).and_return(resp)
187
+ @dav.rename("http://example.com/git/name.git", "http://example.com/git/new_name.git")
188
+ end
189
+
190
+ it "should return response object when status code is 201" do
191
+ resp = mock("Response", :status_code => 201)
192
+ @dav.stub!(:run).and_return(resp)
193
+ @dav.rename("http://example.com/git/name.git", "http://example.com/git/new_name.git").should == resp
194
+ end
195
+
196
+ it "should return false when status is not 201" do
197
+ resp = mock("Response", :status_code => 500, :status => "Five hundred")
198
+ @dav.stub!(:run).and_return resp
199
+ @dav.rename("http://example.com/git/name.git", "http://example.com/git/new_name.git").should be_false
200
+ end
201
+ end
202
+ end
@@ -0,0 +1,13 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe Dreamcatch::Error do
4
+ it "should have a message" do
5
+ msg = Dreamcatch::Error.new("Failure Message")
6
+ msg.to_s.should == "Failure Message"
7
+ end
8
+
9
+ it "should respond to description" do
10
+ msg = Dreamcatch::Error.new("Failure Message")
11
+ msg.should respond_to(:description)
12
+ end
13
+ end
@@ -0,0 +1,176 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe "Dreamcatch::Repo" do
4
+ before :all do
5
+ @repo = Dreamcatch::Repo.new({
6
+ :dir => "/tmp",
7
+ :name => "test.git"
8
+ })
9
+ end
10
+
11
+ it "must provide name for repo name" do
12
+ @repo.instance_variable_get(:@name).should == "test.git"
13
+ @repo.instance_variable_get(:@dir).should == "/tmp"
14
+ end
15
+
16
+ it "throws exception when initialize without repo name" do
17
+ lambda {
18
+ Dreamcatch::Repo.new
19
+ }.should raise_error Dreamcatch::Invalid
20
+ end
21
+
22
+ describe :local_repo do
23
+ it "returns the path to local repo" do
24
+ @repo.local_repo.should == "/tmp/test.git"
25
+ end
26
+ end
27
+
28
+ describe :local_repo_exists? do
29
+ it "returns true when local repo exists" do
30
+ repo_name = "/tmp/test.git"
31
+
32
+ `mkdir #{repo_name}`
33
+ @repo.local_repo_exists?.should be_true
34
+ `rm -rf #{repo_name}`
35
+ end
36
+ end
37
+
38
+ describe :init_bare do
39
+ it "creates a bare git repository" do
40
+ Grit::Repo.should_receive(:init_bare).with("test.git").and_return true
41
+ @repo.init_bare("test.git").should be_true
42
+ end
43
+ end
44
+
45
+ describe :errors do
46
+ it "should return an array" do
47
+ @repo.errors.should be_kind_of(Array)
48
+ end
49
+
50
+ it "should have errors" do
51
+ @repo.webdav.stub!(:exists?).and_return false
52
+ @repo.rename("new_name.git")
53
+ @repo.errors.size.should == 1
54
+ end
55
+
56
+ it "should have errors when trying to delete" do
57
+ @repo.instance_variable_set(:@errors, [])
58
+ @repo.stub!(:exists?).and_return false
59
+ @repo.delete
60
+ @repo.errors.size.should == 1
61
+ end
62
+ end
63
+
64
+ describe :upload_to_webdav do
65
+ it "should execute put from webdav" do
66
+ local_dir, repo_name = "/Users/fernyb", "file.txt"
67
+ @repo.webdav.should_receive(:put).with(local_dir, repo_name)
68
+ @repo.upload_to_webdav(local_dir, repo_name)
69
+ end
70
+ end
71
+
72
+ describe :rename do
73
+ it "should execute webdav.rename when exists and new_name does not" do
74
+ @repo.webdav.should_receive(:exists?).with("test.git").and_return true
75
+ @repo.webdav.should_receive(:exists?).with("new_name.git").and_return false
76
+
77
+ @repo.webdav.should_receive(:rename).with("test.git", "new_name.git").and_return true
78
+ @repo.rename("new_name.git").should be_true
79
+ end
80
+
81
+ it "should not execute webdav.rename when exists and new_name already exists" do
82
+ @repo.webdav.should_receive(:exists?).with("test.git").and_return true
83
+ @repo.webdav.should_receive(:exists?).with("new_name.git").and_return true
84
+
85
+ @repo.webdav.should_not_receive(:rename)
86
+ @repo.rename("new_name.git").should be_nil
87
+ end
88
+
89
+ it "should not execute webdav.rename when not exists" do
90
+ @repo.webdav.should_receive(:exists?).with("test.git").and_return false
91
+ @repo.webdav.should_not_receive(:rename).with("test.git", "new_name")
92
+ @repo.rename("new_name").should be_nil
93
+ end
94
+ end
95
+
96
+ describe :delete_local do
97
+ it "should execute remove_dir from FileUtils and be true" do
98
+ @repo.stub!(:local_repo_exists?).and_return true
99
+ @repo.stub!(:local_repo).and_return "repo.git"
100
+ FileUtils.should_receive(:remove_dir).with("repo.git").and_return(0)
101
+ @repo.delete_local.should be_true
102
+ end
103
+
104
+ it "should execute remove_dir from FileUtils and be nil" do
105
+ @repo.stub!(:local_repo_exists?).and_return true
106
+ @repo.stub!(:local_repo).and_return "repo.git"
107
+ FileUtils.should_receive(:remove_dir).with("repo.git").and_return(1)
108
+ @repo.delete_local.should be_nil
109
+ end
110
+
111
+
112
+ it "should be nil when local repo does not exists" do
113
+ @repo.stub!(:local_repo_exists?).and_return false
114
+ FileUtils.should_not_receive(:remove_dir)
115
+ @repo.delete_local.should be_nil
116
+ end
117
+ end
118
+
119
+ describe :save do
120
+ before :each do
121
+ @repo.stub!(:local_repo_exists?).and_return true
122
+ @repo.stub!(:init_bare).and_return false
123
+ end
124
+
125
+ it "should upload_to_webdav when local repo exists" do
126
+ @repo.should_receive(:upload_to_webdav).with(@repo.instance_variable_get(:@dir), @repo.instance_variable_get(:@name))
127
+ @repo.save
128
+ end
129
+
130
+ it "should init bare local repo and upload to webdav" do
131
+ @repo.stub!(:local_repo_exists?).and_return false
132
+ @repo.should_receive(:init_bare).with(@repo.local_repo).and_return true
133
+ @repo.should_receive(:upload_to_webdav).with(@repo.instance_variable_get(:@dir), @repo.instance_variable_get(:@name))
134
+ @repo.save
135
+ end
136
+ end
137
+
138
+ describe :delete do
139
+ it "should delete repo when it does exists" do
140
+ @repo.webdav.stub!(:exists?).and_return true
141
+ @repo.webdav.should_receive(:delete).with(@repo.instance_variable_get(:@name)).and_return true
142
+ @repo.stub!(:local_repo_exists?).and_return false
143
+
144
+ @repo.delete.should be_true
145
+ end
146
+
147
+ it "should not delete repo when it does not exists" do
148
+ @repo.webdav.stub!(:exists?).and_return false
149
+ @repo.stub!(:local_repo_exists?).and_return false
150
+
151
+ @repo.delete.should be_nil
152
+ end
153
+
154
+ it "should not remote directory when local repo does not exists" do
155
+ @repo.webdav.stub!(:exists?).and_return false
156
+ @repo.stub!(:local_repo_exists?).and_return false
157
+ FileUtils.should_not_receive(:remove_dir).with(@repo.local_repo).and_return false
158
+
159
+ @repo.delete.should be_nil
160
+ end
161
+
162
+ it "should return true when remote file is deleted" do
163
+ @repo.webdav.stub!(:exists?).and_return true
164
+ @repo.webdav.should_receive(:delete).and_return true
165
+
166
+ @repo.delete.should be_true
167
+ end
168
+
169
+ it "should return false when remote file is deleted and fails" do
170
+ @repo.webdav.stub!(:exists?).and_return true
171
+ @repo.webdav.should_receive(:delete).and_return false
172
+
173
+ @repo.delete.should be_false
174
+ end
175
+ end
176
+ end
@@ -0,0 +1,16 @@
1
+ HTTP/1.1 404 Not Found
2
+ Date: Sat, 21 Nov 2009 15:20:06 GMT
3
+ Server: Apache
4
+ Vary: Accept-Encoding
5
+ Content-Length: 329
6
+ Content-Type: text/html; charset=iso-8859-1
7
+
8
+ <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
9
+ <html><head>
10
+ <title>404 Not Found</title>
11
+ </head><body>
12
+ <h1>Not Found</h1>
13
+ <p>The requested URL /git/test.txt was not found on this server.</p>
14
+ <p>Additionally, a 404 Not Found
15
+ error was encountered while trying to use an ErrorDocument to handle the request.</p>
16
+ </body></html>
@@ -0,0 +1,18 @@
1
+ HTTP/1.1 100 Continue
2
+
3
+ HTTP/1.1 201 Created
4
+ Date: Sat, 21 Nov 2009 15:21:40 GMT
5
+ Server: Apache
6
+ Location: http://example.com/git/test.txt
7
+ Vary: Accept-Encoding
8
+ MS-Author-Via: DAV
9
+ Content-Length: 185
10
+ Content-Type: text/html; charset=ISO-8859-1
11
+
12
+ <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
13
+ <html><head>
14
+ <title>201 Created</title>
15
+ </head><body>
16
+ <h1>Created</h1>
17
+ <p>Resource /git/test.txt has been created.</p>
18
+ </body></html>
@@ -0,0 +1,8 @@
1
+ HTTP/1.1 201 Created
2
+ Date: Sat, 21 Nov 2009 15:21:40 GMT
3
+ Server: Apache
4
+ Location: http://example.com/git/test.txt
5
+ Vary: Accept-Encoding
6
+ MS-Author-Via: DAV
7
+ Content-Length: 185
8
+ Content-Type: text/html; charset=ISO-8859-1
@@ -0,0 +1,16 @@
1
+ HTTP/1.1 201 Created
2
+ Date: Sat, 21 Nov 2009 15:21:40 GMT
3
+ Server: Apache
4
+ Location: http://example.com/git/test.txt
5
+ Vary: Accept-Encoding
6
+ MS-Author-Via: DAV
7
+ Content-Length: 185
8
+ Content-Type: text/html; charset=ISO-8859-1
9
+
10
+ <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
11
+ <html><head>
12
+ <title>201 Created</title>
13
+ </head><body>
14
+ <h1>Created</h1>
15
+ <p>Resource /git/test.txt has been created.</p>
16
+ </body></html>
@@ -0,0 +1 @@
1
+ --color
@@ -0,0 +1,19 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
2
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
+ require 'dreamcatch'
4
+ require 'spec'
5
+ require 'spec/autorun'
6
+
7
+
8
+ Spec::Runner.configure do |config|
9
+
10
+ end
11
+
12
+ def response_for(name)
13
+ File.open(File.dirname(__FILE__) + "/fixtures/response/#{name}.txt") {|f| f.read }
14
+ end
15
+
16
+
17
+ def response_for_into_array(name)
18
+ f = File.new(File.dirname(__FILE__) + "/fixtures/response/#{name}.txt")
19
+ end
metadata ADDED
@@ -0,0 +1,103 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: dreamcatch
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Fernando Barajas
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-11-27 00:00:00 -08:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: rspec
17
+ type: :development
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 1.2.9
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: grit
27
+ type: :runtime
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: "0"
34
+ version:
35
+ description: A simple way to add and remove git repos on dreamhost webdav
36
+ email: fernyb@fernyb.net
37
+ executables: []
38
+
39
+ extensions: []
40
+
41
+ extra_rdoc_files:
42
+ - LICENSE
43
+ - README.rdoc
44
+ files:
45
+ - .gitignore
46
+ - LICENSE
47
+ - README.rdoc
48
+ - Rakefile
49
+ - VERSION
50
+ - dreamcatch.gemspec
51
+ - lib/dreamcatch.rb
52
+ - lib/dreamcatch/config.rb
53
+ - lib/dreamcatch/dav.rb
54
+ - lib/dreamcatch/dav_response.rb
55
+ - lib/dreamcatch/error.rb
56
+ - lib/dreamcatch/repo.rb
57
+ - lib/dreamcatch/web_dav.rb
58
+ - spec/dreamcatch/config_spec.rb
59
+ - spec/dreamcatch/dav_response_spec.rb
60
+ - spec/dreamcatch/dav_spec.rb
61
+ - spec/dreamcatch/error_spec.rb
62
+ - spec/dreamcatch/repo_spec.rb
63
+ - spec/fixtures/response/404_not_found.txt
64
+ - spec/fixtures/response/put.txt
65
+ - spec/fixtures/response/put_no_body.txt
66
+ - spec/fixtures/response/put_two.txt
67
+ - spec/spec.opts
68
+ - spec/spec_helper.rb
69
+ has_rdoc: true
70
+ homepage: http://github.com/fernyb/dreamcatch
71
+ licenses: []
72
+
73
+ post_install_message:
74
+ rdoc_options:
75
+ - --charset=UTF-8
76
+ require_paths:
77
+ - lib
78
+ required_ruby_version: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: "0"
83
+ version:
84
+ required_rubygems_version: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: "0"
89
+ version:
90
+ requirements: []
91
+
92
+ rubyforge_project:
93
+ rubygems_version: 1.3.5
94
+ signing_key:
95
+ specification_version: 3
96
+ summary: Git on Dreamhost WebDAV
97
+ test_files:
98
+ - spec/dreamcatch/config_spec.rb
99
+ - spec/dreamcatch/dav_response_spec.rb
100
+ - spec/dreamcatch/dav_spec.rb
101
+ - spec/dreamcatch/error_spec.rb
102
+ - spec/dreamcatch/repo_spec.rb
103
+ - spec/spec_helper.rb