designshell 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +18 -0
- data/.idea/.name +1 -0
- data/.idea/.rakeTasks +7 -0
- data/.idea/codeStyleSettings.xml +13 -0
- data/.idea/compiler.xml +25 -0
- data/.idea/copyright/profiles_settings.xml +5 -0
- data/.idea/encodings.xml +5 -0
- data/.idea/misc.xml +11 -0
- data/.idea/modules.xml +11 -0
- data/.idea/scopes/scope_settings.xml +5 -0
- data/.idea/vcs.xml +9 -0
- data/Gemfile +2 -0
- data/Gemfile.lock +196 -0
- data/LICENSE +22 -0
- data/README.md +35 -0
- data/README.rdoc +6 -0
- data/Rakefile +46 -0
- data/bin/designshelld.example.sh +5 -0
- data/bin/designshelld.example2.sh +3 -0
- data/bin/designshellserver +22 -0
- data/bin/ds +177 -0
- data/designshell.gemspec +40 -0
- data/designshell.iml +84 -0
- data/designshell.rdoc +5 -0
- data/features/designshell.feature +8 -0
- data/features/step_definitions/designshell_steps.rb +6 -0
- data/features/support/env.rb +15 -0
- data/lib/buzzcore_mods.rb +19 -0
- data/lib/designshell/context.rb +48 -0
- data/lib/designshell/core.rb +78 -0
- data/lib/designshell/deploy_plan.rb +40 -0
- data/lib/designshell/key_chain.rb +40 -0
- data/lib/designshell/repo.rb +112 -0
- data/lib/designshell/repo_server.rb +25 -0
- data/lib/designshell/site_client.rb +141 -0
- data/lib/designshell/utils.rb +18 -0
- data/lib/designshell/version.rb +3 -0
- data/lib/designshell.rb +19 -0
- data/lib/designshellserver/command.rb +180 -0
- data/lib/designshellserver/core.rb +41 -0
- data/lib/designshellserver.rb +17 -0
- data/spec/KeyChain_spec.rb +94 -0
- data/spec/RepoServer_spec.rb +54 -0
- data/spec/Repo_spec.rb +105 -0
- data/spec/build_spec.rb +29 -0
- data/spec/client_to_server_spec.rb +111 -0
- data/spec/designshell_context_spec.rb +18 -0
- data/spec/designshell_core_spec.rb +45 -0
- data/spec/rspec_helper.rb +8 -0
- data/spec/server/deploy_spec.rb +210 -0
- data/spec/server/dummy_spec.rb +52 -0
- data/spec/site_client_spec.rb +90 -0
- data/test/default_test.rb +14 -0
- data/test/test_helper.rb +9 -0
- data/testmart.iml +9 -0
- metadata +390 -0
data/designshell.gemspec
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
# Ensure we require the local version and not one we might have installed already
|
2
|
+
require File.join([File.dirname(__FILE__),'lib','designshell','version.rb'])
|
3
|
+
spec = Gem::Specification.new do |s|
|
4
|
+
s.name = 'designshell'
|
5
|
+
s.version = DesignShell::VERSION
|
6
|
+
s.author = 'Gary McGhee'
|
7
|
+
s.email = 'contact@buzzware.com.au'
|
8
|
+
s.summary = 'DesignShell is the shell for designers'
|
9
|
+
s.description = 'All-round workflow tool for designers. Enables designers to comfortably use geek goodness like git, git deploy, SASS etc'
|
10
|
+
s.require_paths = ["lib"]
|
11
|
+
s.homepage = 'http://github.com/buzzware/designshell'
|
12
|
+
s.platform = Gem::Platform::RUBY
|
13
|
+
# Add your other files here if you make them
|
14
|
+
s.files = `git ls-files`.split($\)
|
15
|
+
s.bindir = 'bin'
|
16
|
+
s.executables = s.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
17
|
+
s.test_files = s.files.grep(%r{^(test|spec|features)/})
|
18
|
+
#s.has_rdoc = true
|
19
|
+
#s.extra_rdoc_files = ['README.rdoc','designshell.rdoc']
|
20
|
+
#s.rdoc_options << '--title' << 'designshell' << '--main' << 'README.rdoc' << '-ri'
|
21
|
+
s.add_development_dependency('rake')
|
22
|
+
s.add_development_dependency('rspec')
|
23
|
+
s.add_development_dependency('rspec-core')
|
24
|
+
s.add_development_dependency('rdoc')
|
25
|
+
s.add_development_dependency('aruba')
|
26
|
+
s.add_development_dependency('ruby-debug')
|
27
|
+
s.add_runtime_dependency('gli','2.5.0')
|
28
|
+
s.add_runtime_dependency('termios')
|
29
|
+
s.add_runtime_dependency('highline')
|
30
|
+
s.add_runtime_dependency('git')
|
31
|
+
s.add_runtime_dependency('middleman')
|
32
|
+
s.add_runtime_dependency('buzzcore')
|
33
|
+
s.add_runtime_dependency('POpen4')
|
34
|
+
s.add_runtime_dependency('bitbucket_rest_api')
|
35
|
+
s.add_runtime_dependency('osx_keychain')
|
36
|
+
s.add_runtime_dependency('json')
|
37
|
+
s.add_runtime_dependency('net_dav')
|
38
|
+
s.add_runtime_dependency('net-ssh')
|
39
|
+
|
40
|
+
end
|
data/designshell.iml
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<module type="RUBY_MODULE" version="4">
|
3
|
+
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
4
|
+
<exclude-output />
|
5
|
+
<content url="file://$MODULE_DIR$" />
|
6
|
+
<orderEntry type="jdk" jdkName="RVM: ruby-1.8.7-p358 [dash]" jdkType="RUBY_SDK" />
|
7
|
+
<orderEntry type="sourceFolder" forTests="false" />
|
8
|
+
<orderEntry type="library" scope="PROVIDED" name="POpen4 (v0.1.4, RVM: ruby-1.8.7-p358 [dash]) [gem]" level="application" />
|
9
|
+
<orderEntry type="library" scope="PROVIDED" name="Platform (v0.4.0, RVM: ruby-1.8.7-p358 [dash]) [gem]" level="application" />
|
10
|
+
<orderEntry type="library" scope="PROVIDED" name="RubyInline (v3.12.0, RVM: ruby-1.8.7-p358 [dash]) [gem]" level="application" />
|
11
|
+
<orderEntry type="library" scope="PROVIDED" name="ZenTest (v4.8.3, RVM: ruby-1.8.7-p358 [dash]) [gem]" level="application" />
|
12
|
+
<orderEntry type="library" scope="PROVIDED" name="activesupport (v3.2.11, RVM: ruby-1.8.7-p358 [dash]) [gem]" level="application" />
|
13
|
+
<orderEntry type="library" scope="PROVIDED" name="aruba (v0.5.1, RVM: ruby-1.8.7-p358 [dash]) [gem]" level="application" />
|
14
|
+
<orderEntry type="library" scope="PROVIDED" name="bitbucket_rest_api (v0.1.1, RVM: ruby-1.8.7-p358 [dash]) [gem]" level="application" />
|
15
|
+
<orderEntry type="library" scope="PROVIDED" name="builder (v3.1.4, RVM: ruby-1.8.7-p358 [dash]) [gem]" level="application" />
|
16
|
+
<orderEntry type="library" scope="PROVIDED" name="bundler (v1.1.3, RVM: ruby-1.8.7-p358 [dash]) [gem]" level="application" />
|
17
|
+
<orderEntry type="library" scope="PROVIDED" name="buzzcore (v0.6.4, RVM: ruby-1.8.7-p358 [dash]) [gem]" level="application" />
|
18
|
+
<orderEntry type="library" scope="PROVIDED" name="childprocess (v0.3.6, RVM: ruby-1.8.7-p358 [dash]) [gem]" level="application" />
|
19
|
+
<orderEntry type="library" scope="PROVIDED" name="chunky_png (v1.2.7, RVM: ruby-1.8.7-p358 [dash]) [gem]" level="application" />
|
20
|
+
<orderEntry type="library" scope="PROVIDED" name="coffee-script (v2.2.0, RVM: ruby-1.8.7-p358 [dash]) [gem]" level="application" />
|
21
|
+
<orderEntry type="library" scope="PROVIDED" name="coffee-script-source (v1.3.3, RVM: ruby-1.8.7-p358 [dash]) [gem]" level="application" />
|
22
|
+
<orderEntry type="library" scope="PROVIDED" name="columnize (v0.3.6, RVM: ruby-1.8.7-p358 [dash]) [gem]" level="application" />
|
23
|
+
<orderEntry type="library" scope="PROVIDED" name="compass (v0.12.2, RVM: ruby-1.8.7-p358 [dash]) [gem]" level="application" />
|
24
|
+
<orderEntry type="library" scope="PROVIDED" name="cucumber (v1.2.1, RVM: ruby-1.8.7-p358 [dash]) [gem]" level="application" />
|
25
|
+
<orderEntry type="library" scope="PROVIDED" name="diff-lcs (v1.1.3, RVM: ruby-1.8.7-p358 [dash]) [gem]" level="application" />
|
26
|
+
<orderEntry type="library" scope="PROVIDED" name="execjs (v1.4.0, RVM: ruby-1.8.7-p358 [dash]) [gem]" level="application" />
|
27
|
+
<orderEntry type="library" scope="PROVIDED" name="faraday (v0.8.4, RVM: ruby-1.8.7-p358 [dash]) [gem]" level="application" />
|
28
|
+
<orderEntry type="library" scope="PROVIDED" name="faraday_middleware (v0.8.8, RVM: ruby-1.8.7-p358 [dash]) [gem]" level="application" />
|
29
|
+
<orderEntry type="library" scope="PROVIDED" name="ffi (v1.3.1, RVM: ruby-1.8.7-p358 [dash]) [gem]" level="application" />
|
30
|
+
<orderEntry type="library" scope="PROVIDED" name="fssm (v0.2.9, RVM: ruby-1.8.7-p358 [dash]) [gem]" level="application" />
|
31
|
+
<orderEntry type="library" scope="PROVIDED" name="gherkin (v2.11.5, RVM: ruby-1.8.7-p358 [dash]) [gem]" level="application" />
|
32
|
+
<orderEntry type="library" scope="PROVIDED" name="git (v1.2.5, RVM: ruby-1.8.7-p358 [dash]) [gem]" level="application" />
|
33
|
+
<orderEntry type="library" scope="PROVIDED" name="gli (v2.5.0, RVM: ruby-1.8.7-p358 [dash]) [gem]" level="application" />
|
34
|
+
<orderEntry type="library" scope="PROVIDED" name="haml (v3.1.7, RVM: ruby-1.8.7-p358 [dash]) [gem]" level="application" />
|
35
|
+
<orderEntry type="library" scope="PROVIDED" name="hashie (v1.2.0, RVM: ruby-1.8.7-p358 [dash]) [gem]" level="application" />
|
36
|
+
<orderEntry type="library" scope="PROVIDED" name="highline (v1.6.15, RVM: ruby-1.8.7-p358 [dash]) [gem]" level="application" />
|
37
|
+
<orderEntry type="library" scope="PROVIDED" name="hike (v1.2.1, RVM: ruby-1.8.7-p358 [dash]) [gem]" level="application" />
|
38
|
+
<orderEntry type="library" scope="PROVIDED" name="http_router (v0.10.2, RVM: ruby-1.8.7-p358 [dash]) [gem]" level="application" />
|
39
|
+
<orderEntry type="library" scope="PROVIDED" name="i18n (v0.6.1, RVM: ruby-1.8.7-p358 [dash]) [gem]" level="application" />
|
40
|
+
<orderEntry type="library" scope="PROVIDED" name="json (v1.7.6, RVM: ruby-1.8.7-p358 [dash]) [gem]" level="application" />
|
41
|
+
<orderEntry type="library" scope="PROVIDED" name="linecache (v0.46, RVM: ruby-1.8.7-p358 [dash]) [gem]" level="application" />
|
42
|
+
<orderEntry type="library" scope="PROVIDED" name="listen (v0.5.3, RVM: ruby-1.8.7-p358 [dash]) [gem]" level="application" />
|
43
|
+
<orderEntry type="library" scope="PROVIDED" name="maruku (v0.6.1, RVM: ruby-1.8.7-p358 [dash]) [gem]" level="application" />
|
44
|
+
<orderEntry type="library" scope="PROVIDED" name="middleman (v3.0.9, RVM: ruby-1.8.7-p358 [dash]) [gem]" level="application" />
|
45
|
+
<orderEntry type="library" scope="PROVIDED" name="middleman-core (v3.0.9, RVM: ruby-1.8.7-p358 [dash]) [gem]" level="application" />
|
46
|
+
<orderEntry type="library" scope="PROVIDED" name="middleman-more (v3.0.9, RVM: ruby-1.8.7-p358 [dash]) [gem]" level="application" />
|
47
|
+
<orderEntry type="library" scope="PROVIDED" name="middleman-sprockets (v3.0.6, RVM: ruby-1.8.7-p358 [dash]) [gem]" level="application" />
|
48
|
+
<orderEntry type="library" scope="PROVIDED" name="multi_json (v1.5.0, RVM: ruby-1.8.7-p358 [dash]) [gem]" level="application" />
|
49
|
+
<orderEntry type="library" scope="PROVIDED" name="multipart-post (v1.1.5, RVM: ruby-1.8.7-p358 [dash]) [gem]" level="application" />
|
50
|
+
<orderEntry type="library" scope="PROVIDED" name="net-ssh (v2.6.3, RVM: ruby-1.8.7-p358 [dash]) [gem]" level="application" />
|
51
|
+
<orderEntry type="library" scope="PROVIDED" name="net_dav (v0.5.0, RVM: ruby-1.8.7-p358 [dash]) [gem]" level="application" />
|
52
|
+
<orderEntry type="library" scope="PROVIDED" name="nokogiri (v1.5.6, RVM: ruby-1.8.7-p358 [dash]) [gem]" level="application" />
|
53
|
+
<orderEntry type="library" scope="PROVIDED" name="open4 (v1.3.0, RVM: ruby-1.8.7-p358 [dash]) [gem]" level="application" />
|
54
|
+
<orderEntry type="library" scope="PROVIDED" name="osx_keychain (v1.0.0, RVM: ruby-1.8.7-p358 [dash]) [gem]" level="application" />
|
55
|
+
<orderEntry type="library" scope="PROVIDED" name="padrino-core (v0.10.7, RVM: ruby-1.8.7-p358 [dash]) [gem]" level="application" />
|
56
|
+
<orderEntry type="library" scope="PROVIDED" name="padrino-helpers (v0.10.7, RVM: ruby-1.8.7-p358 [dash]) [gem]" level="application" />
|
57
|
+
<orderEntry type="library" scope="PROVIDED" name="rack (v1.4.1, RVM: ruby-1.8.7-p358 [dash]) [gem]" level="application" />
|
58
|
+
<orderEntry type="library" scope="PROVIDED" name="rack-protection (v1.3.2, RVM: ruby-1.8.7-p358 [dash]) [gem]" level="application" />
|
59
|
+
<orderEntry type="library" scope="PROVIDED" name="rack-test (v0.6.2, RVM: ruby-1.8.7-p358 [dash]) [gem]" level="application" />
|
60
|
+
<orderEntry type="library" scope="PROVIDED" name="rake (v10.0.3, RVM: ruby-1.8.7-p358 [dash]) [gem]" level="application" />
|
61
|
+
<orderEntry type="library" scope="PROVIDED" name="rb-fsevent (v0.9.3, RVM: ruby-1.8.7-p358 [dash]) [gem]" level="application" />
|
62
|
+
<orderEntry type="library" scope="PROVIDED" name="rb-inotify (v0.8.8, RVM: ruby-1.8.7-p358 [dash]) [gem]" level="application" />
|
63
|
+
<orderEntry type="library" scope="PROVIDED" name="rbx-require-relative (v0.0.9, RVM: ruby-1.8.7-p358 [dash]) [gem]" level="application" />
|
64
|
+
<orderEntry type="library" scope="PROVIDED" name="rdoc (v3.12, RVM: ruby-1.8.7-p358 [dash]) [gem]" level="application" />
|
65
|
+
<orderEntry type="library" scope="PROVIDED" name="rspec (v2.12.0, RVM: ruby-1.8.7-p358 [dash]) [gem]" level="application" />
|
66
|
+
<orderEntry type="library" scope="PROVIDED" name="rspec-core (v2.12.2, RVM: ruby-1.8.7-p358 [dash]) [gem]" level="application" />
|
67
|
+
<orderEntry type="library" scope="PROVIDED" name="rspec-expectations (v2.12.1, RVM: ruby-1.8.7-p358 [dash]) [gem]" level="application" />
|
68
|
+
<orderEntry type="library" scope="PROVIDED" name="rspec-mocks (v2.12.1, RVM: ruby-1.8.7-p358 [dash]) [gem]" level="application" />
|
69
|
+
<orderEntry type="library" scope="PROVIDED" name="ruby-debug (v0.10.4, RVM: ruby-1.8.7-p358 [dash]) [gem]" level="application" />
|
70
|
+
<orderEntry type="library" scope="PROVIDED" name="ruby-debug-base (v0.10.4, RVM: ruby-1.8.7-p358 [dash]) [gem]" level="application" />
|
71
|
+
<orderEntry type="library" scope="PROVIDED" name="sass (v3.2.5, RVM: ruby-1.8.7-p358 [dash]) [gem]" level="application" />
|
72
|
+
<orderEntry type="library" scope="PROVIDED" name="simple_oauth (v0.2.0, RVM: ruby-1.8.7-p358 [dash]) [gem]" level="application" />
|
73
|
+
<orderEntry type="library" scope="PROVIDED" name="sinatra (v1.3.3, RVM: ruby-1.8.7-p358 [dash]) [gem]" level="application" />
|
74
|
+
<orderEntry type="library" scope="PROVIDED" name="sprockets (v2.4.5, RVM: ruby-1.8.7-p358 [dash]) [gem]" level="application" />
|
75
|
+
<orderEntry type="library" scope="PROVIDED" name="sprockets-sass (v0.9.1, RVM: ruby-1.8.7-p358 [dash]) [gem]" level="application" />
|
76
|
+
<orderEntry type="library" scope="PROVIDED" name="syntax (v1.0.0, RVM: ruby-1.8.7-p358 [dash]) [gem]" level="application" />
|
77
|
+
<orderEntry type="library" scope="PROVIDED" name="termios (v0.9.4, RVM: ruby-1.8.7-p358 [dash]) [gem]" level="application" />
|
78
|
+
<orderEntry type="library" scope="PROVIDED" name="thor (v0.15.4, RVM: ruby-1.8.7-p358 [dash]) [gem]" level="application" />
|
79
|
+
<orderEntry type="library" scope="PROVIDED" name="tilt (v1.3.3, RVM: ruby-1.8.7-p358 [dash]) [gem]" level="application" />
|
80
|
+
<orderEntry type="library" scope="PROVIDED" name="uglifier (v1.2.7, RVM: ruby-1.8.7-p358 [dash]) [gem]" level="application" />
|
81
|
+
<orderEntry type="library" scope="PROVIDED" name="url_mount (v0.2.1, RVM: ruby-1.8.7-p358 [dash]) [gem]" level="application" />
|
82
|
+
</component>
|
83
|
+
</module>
|
84
|
+
|
data/designshell.rdoc
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
#require 'aruba/cucumber'
|
2
|
+
#
|
3
|
+
#ENV['PATH'] = "#{File.expand_path(File.dirname(__FILE__) + '/../../bin')}#{File::PATH_SEPARATOR}#{ENV['PATH']}"
|
4
|
+
#LIB_DIR = File.join(File.expand_path(File.dirname(__FILE__)),'..','..','lib')
|
5
|
+
#
|
6
|
+
#Before do
|
7
|
+
# # Using "announce" causes massive warnings on 1.9.2
|
8
|
+
# @puts = true
|
9
|
+
# @original_rubylib = ENV['RUBYLIB']
|
10
|
+
# ENV['RUBYLIB'] = LIB_DIR + File::PATH_SEPARATOR + ENV['RUBYLIB'].to_s
|
11
|
+
#end
|
12
|
+
#
|
13
|
+
#After do
|
14
|
+
# ENV['RUBYLIB'] = @original_rubylib
|
15
|
+
#end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
MiscUtils.module_eval do
|
2
|
+
# Like bite, but returns the first match instead of the subject
|
3
|
+
#if !self.instance_methods.include? "extract!"
|
4
|
+
#end
|
5
|
+
def self.ensure_slashes(aString,aLeading,aTrailing)
|
6
|
+
if (aLeading)
|
7
|
+
aString = ensure_prefix(aString,'/')
|
8
|
+
else
|
9
|
+
aString = aString.bite('/')
|
10
|
+
end
|
11
|
+
if (aTrailing)
|
12
|
+
aString = ensure_suffix(aString,'/')
|
13
|
+
else
|
14
|
+
aString = aString.chomp('/') unless aString=='/' && aLeading
|
15
|
+
end
|
16
|
+
aString
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module DesignShell
|
2
|
+
|
3
|
+
class Context
|
4
|
+
attr_reader :global_options,:options,:pwd,:argv,:env,:stdout,:stdin,:stderr,:credentials,:key_chain
|
5
|
+
attr_writer :pwd
|
6
|
+
|
7
|
+
def initialize(aValues=nil)
|
8
|
+
return if !aValues
|
9
|
+
@global_options = aValues[:global_options]
|
10
|
+
@options = aValues[:options]
|
11
|
+
@pwd = MiscUtils.real_path(Dir.pwd)
|
12
|
+
@argv = aValues[:argv]
|
13
|
+
@env = aValues[:env]
|
14
|
+
@stdout = aValues[:stdout]
|
15
|
+
@stdin = aValues[:stdin]
|
16
|
+
@stderr = aValues[:stderr]
|
17
|
+
@credentials = aValues[:credentials]
|
18
|
+
@key_chain = aValues[:key_chain]
|
19
|
+
end
|
20
|
+
|
21
|
+
# http://thinkingdigitally.com/archive/capturing-output-from-puts-in-ruby/
|
22
|
+
#class SimpleSemParserTest < Test::Unit::TestCase
|
23
|
+
# def test_set_stmt_write
|
24
|
+
# out = capture_stdout do
|
25
|
+
# parser = SimpleSemParser.new
|
26
|
+
# parser.parse('set write, "Hello World!"').execute
|
27
|
+
# end
|
28
|
+
# assert_equal "Hello World!\n", out.string
|
29
|
+
# end
|
30
|
+
#end
|
31
|
+
def capture_stdout
|
32
|
+
stdout_before = @stdout
|
33
|
+
out = StringIO.new
|
34
|
+
@stdout = out
|
35
|
+
yield
|
36
|
+
return out.string
|
37
|
+
ensure
|
38
|
+
@stdout = stdout_before
|
39
|
+
end
|
40
|
+
|
41
|
+
def find_git_root
|
42
|
+
git_folder = MiscUtils.find_upwards(@pwd,'.git')
|
43
|
+
return git_folder && git_folder.chomp('/.git')
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
module DesignShell
|
2
|
+
class Core
|
3
|
+
|
4
|
+
attr_reader :repo,:configured,:context
|
5
|
+
|
6
|
+
def initialize(aDependencies=nil)
|
7
|
+
@@instance = self unless (defined? @@instance) && @@instance
|
8
|
+
if aDependencies
|
9
|
+
@context = aDependencies[:context]
|
10
|
+
@repo = aDependencies[:repo]
|
11
|
+
@keyChain = aDependencies[:keyChain] || @context.key_chain
|
12
|
+
end
|
13
|
+
configure(@context) if @context
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.instance
|
17
|
+
(defined? @@instance) && @@instance
|
18
|
+
end
|
19
|
+
|
20
|
+
def configure(aContext)
|
21
|
+
@configured = true
|
22
|
+
end
|
23
|
+
|
24
|
+
def ensure_repo_open
|
25
|
+
if (!@repo && @context)
|
26
|
+
if git_root = @context.find_git_root
|
27
|
+
@repo = DesignShell::Repo.new
|
28
|
+
@repo.open git_root
|
29
|
+
end
|
30
|
+
end
|
31
|
+
raise "unable to open repository" unless @repo.open?
|
32
|
+
@repo
|
33
|
+
end
|
34
|
+
|
35
|
+
def ensure_deploy_server
|
36
|
+
@conn ||= Net::SSH.start(@context.credentials[:deploy_host],nil)
|
37
|
+
end
|
38
|
+
|
39
|
+
def deploy_plan(*args)
|
40
|
+
return @deploy_plan if args.empty?
|
41
|
+
plan = args.first
|
42
|
+
if plan.is_a?(DesignShell::DeployPlan)
|
43
|
+
@deploy_plan = plan
|
44
|
+
elsif plan
|
45
|
+
@deploy_plan = DesignShell::DeployPlan.new(:core => self,:plan => plan)
|
46
|
+
end
|
47
|
+
@deploy_plan
|
48
|
+
end
|
49
|
+
|
50
|
+
def build
|
51
|
+
response = POpen4::shell('ls')
|
52
|
+
# puts result[:stdout]
|
53
|
+
end
|
54
|
+
|
55
|
+
def deploy
|
56
|
+
ensure_repo_open
|
57
|
+
deploy_branch = 'master'
|
58
|
+
deploy_plan(repo.get_file_content('.deploy_plan.xml',deploy_branch))
|
59
|
+
params = deploy_plan.deploy_items_values.clone
|
60
|
+
params['site'] = deploy_plan.site
|
61
|
+
params['repo_url'] = repo.origin.url
|
62
|
+
call_server_command('DEPLOY',params)
|
63
|
+
end
|
64
|
+
|
65
|
+
def call_server_command(aCommand, aParams=nil)
|
66
|
+
#ds_conn = ensure_deploy_server
|
67
|
+
command = aCommand
|
68
|
+
command += " " + JSON.generate(aParams) if aParams
|
69
|
+
#result = ds_conn.exec!(command)
|
70
|
+
result = nil
|
71
|
+
Net::SSH.start(@context.credentials[:deploy_host],nil) do |ssh|
|
72
|
+
result = ssh.exec!(command)
|
73
|
+
end
|
74
|
+
result
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module DesignShell
|
2
|
+
class DeployPlan
|
3
|
+
def initialize(aConfig=nil)
|
4
|
+
return if !aConfig
|
5
|
+
@core = aConfig[:core]
|
6
|
+
read(aConfig[:plan]) if aConfig[:plan]
|
7
|
+
end
|
8
|
+
|
9
|
+
def read(aDeployPlan)
|
10
|
+
@deployPlanNode = XmlUtils.get_xml_root(aDeployPlan)
|
11
|
+
end
|
12
|
+
|
13
|
+
def site
|
14
|
+
XmlUtils.peek_node_value(@deployPlanNode,'/deployPlan/@site')
|
15
|
+
end
|
16
|
+
|
17
|
+
def deploy_node() # later accept criteria
|
18
|
+
XmlUtils.single_node(@deployPlanNode,'/deployPlan/plan/deploy')
|
19
|
+
end
|
20
|
+
|
21
|
+
def key_chain
|
22
|
+
@core && @core.context && @core.context.key_chain
|
23
|
+
end
|
24
|
+
|
25
|
+
def deploy_items_values(aDeployNode=nil)
|
26
|
+
aDeployNode ||= deploy_node()
|
27
|
+
result = {}
|
28
|
+
aDeployNode.get_elements('item').each do |n|
|
29
|
+
next unless name = XmlUtils.attr(n,'name')
|
30
|
+
if text = n.text.to_nil # value in node
|
31
|
+
result[name] = text
|
32
|
+
elsif key_chain # value in keyChain
|
33
|
+
key = XmlUtils.attr(n,'key') || name
|
34
|
+
result[name] = key_chain[key]
|
35
|
+
end
|
36
|
+
end
|
37
|
+
result
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module DesignShell
|
2
|
+
class KeyChain
|
3
|
+
|
4
|
+
def initialize(aNamespace)
|
5
|
+
@keychain = OSXKeychain.new
|
6
|
+
@namespace = aNamespace
|
7
|
+
end
|
8
|
+
|
9
|
+
def [](aKey)
|
10
|
+
get(aKey)
|
11
|
+
end
|
12
|
+
|
13
|
+
def []=(aKey,aValue)
|
14
|
+
set(aKey,aValue)
|
15
|
+
end
|
16
|
+
|
17
|
+
def set(aKey,aValue=nil,aPrefix='')
|
18
|
+
if (aKey.is_a?(String) || aKey.is_a?(Symbol))
|
19
|
+
@keychain[@namespace,aPrefix.to_s+aKey.to_s] = aValue
|
20
|
+
elsif aKey.is_a?(Hash)
|
21
|
+
prefix = aValue || aPrefix
|
22
|
+
aKey.each {|k,v| set(k,v,prefix)}
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def get(aKey,aPrefix=nil,aKeepPrefix=false)
|
27
|
+
if (aKey.is_a?(Array))
|
28
|
+
result = {}
|
29
|
+
aKey.each do |k|
|
30
|
+
storeKey = (aKeepPrefix ? aPrefix.to_s+k.to_s : k.to_s)
|
31
|
+
v = get(k.to_s,aPrefix)
|
32
|
+
result[storeKey] = v
|
33
|
+
end
|
34
|
+
return result
|
35
|
+
else
|
36
|
+
return @keychain[@namespace,aPrefix.to_s+aKey.to_s]
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
Git::Lib.class_eval do
|
2
|
+
public :command, :command_lines
|
3
|
+
end
|
4
|
+
|
5
|
+
module DesignShell
|
6
|
+
class Repo
|
7
|
+
|
8
|
+
attr_reader :git,:configured
|
9
|
+
|
10
|
+
GIT_METHODS = [:commit,:add,:reset_hard,:path,:clone,:log,:size,:branches,:status,:remotes,:pull,:fetch,:push,:merge]
|
11
|
+
|
12
|
+
def initialize(aDesignShell=nil)
|
13
|
+
@ds = aDesignShell
|
14
|
+
end
|
15
|
+
|
16
|
+
def method_missing(sym, *args, &block)
|
17
|
+
if @git && GIT_METHODS.include?(sym)
|
18
|
+
@git.send sym, *args, &block
|
19
|
+
else
|
20
|
+
super
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
#def configure(aContext=nil)
|
25
|
+
# # set @path
|
26
|
+
# @configured = true
|
27
|
+
#end
|
28
|
+
|
29
|
+
def open(aPath)
|
30
|
+
@git = Git.open(aPath, :log => Logger.new(STDOUT))
|
31
|
+
end
|
32
|
+
|
33
|
+
def init(*args)
|
34
|
+
@git = Git.init(*args)
|
35
|
+
end
|
36
|
+
|
37
|
+
def clone(aUrl,aPath)
|
38
|
+
@git = Git::clone(aUrl,aPath)
|
39
|
+
end
|
40
|
+
|
41
|
+
def open?
|
42
|
+
!!@git
|
43
|
+
end
|
44
|
+
|
45
|
+
def empty?
|
46
|
+
!@git.branches[0]
|
47
|
+
end
|
48
|
+
|
49
|
+
def commit_all(*args)
|
50
|
+
result = begin
|
51
|
+
@git.commit_all(*args)
|
52
|
+
rescue Git::GitExecuteError => e
|
53
|
+
if e.message.index("nothing to commit (working directory clean)")
|
54
|
+
nil
|
55
|
+
else
|
56
|
+
raise e
|
57
|
+
end
|
58
|
+
end
|
59
|
+
result = commitFromString(result)
|
60
|
+
result
|
61
|
+
end
|
62
|
+
|
63
|
+
# "[master (root-commit) 6bdd9e1] first commit 1 files changed, 1 insertions(+), 0 deletions(-) create mode 100644 file1.txt"
|
64
|
+
def commitFromString(aString)
|
65
|
+
return nil if !aString || aString.empty?
|
66
|
+
sha = aString.scan(/ ([a-f0-9]+)\]/).flatten.first
|
67
|
+
@git.gcommit(sha)
|
68
|
+
end
|
69
|
+
|
70
|
+
def path
|
71
|
+
@git.dir.path
|
72
|
+
end
|
73
|
+
|
74
|
+
def origin
|
75
|
+
@git.remotes.find {|r| r.name=='origin'}
|
76
|
+
end
|
77
|
+
|
78
|
+
def url
|
79
|
+
(o = origin) && o.url
|
80
|
+
end
|
81
|
+
|
82
|
+
def checkout(commit=nil,branch=nil)
|
83
|
+
specific_commit = !!commit && !commit.index('HEAD')
|
84
|
+
if specific_commit
|
85
|
+
@git.checkout commit
|
86
|
+
else
|
87
|
+
branch ||= 'master'
|
88
|
+
@git.checkout(branch)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def branch
|
93
|
+
@git.current_branch
|
94
|
+
end
|
95
|
+
|
96
|
+
def head
|
97
|
+
@git.log.first
|
98
|
+
end
|
99
|
+
|
100
|
+
# git --no-pager diff --name-status 26bb87c3981 191d64820f2b
|
101
|
+
# result is array of paths prefixed with status letter then a tab
|
102
|
+
# see http://git-scm.com/docs/git-diff under --diff-filter=
|
103
|
+
# Added (A), Copied (C), Deleted (D), Modified (M), Renamed (R), have their type (i.e. regular file, symlink, submodule, ...) changed (T)
|
104
|
+
def changesBetweenCommits(aFromCommit, aToCommit)
|
105
|
+
@git.lib.command_lines('diff',['--name-status',aFromCommit,aToCommit])
|
106
|
+
end
|
107
|
+
|
108
|
+
def get_file_content(aPath,aCommitOrBranch=nil)
|
109
|
+
@git.lib.command('show',[[aCommitOrBranch||'master',aPath].join(':')]) rescue nil
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'bitbucket_rest_api'
|
2
|
+
|
3
|
+
module DesignShell
|
4
|
+
class RepoServer
|
5
|
+
|
6
|
+
DELEGATE_METHODS = [:user,:oauth_token,:oauth_secret,:basic_auth,:login,:password,:adapter,:adapter=,:setup]
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
@bitbucket = BitBucket::Client.new({})
|
10
|
+
end
|
11
|
+
|
12
|
+
def method_missing(sym, *args, &block)
|
13
|
+
if @bitbucket && DELEGATE_METHODS.include?(sym)
|
14
|
+
@bitbucket.send sym, *args, &block
|
15
|
+
else
|
16
|
+
super
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def repos
|
21
|
+
@bitbucket.repos.all
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,141 @@
|
|
1
|
+
module DesignShell
|
2
|
+
|
3
|
+
# might have to work on net_dav to support curl with put ie implement request_sending_body
|
4
|
+
# http://curb.rubyforge.org/classes/Curl/Easy.html
|
5
|
+
#
|
6
|
+
|
7
|
+
class SiteClient
|
8
|
+
|
9
|
+
attr_accessor :deploy_status_file
|
10
|
+
|
11
|
+
def initialize(aConfig)
|
12
|
+
#@context = aContext
|
13
|
+
@server_path = MiscUtils.remove_slash(aConfig[:site_url])
|
14
|
+
site_username = aConfig[:site_username]
|
15
|
+
site_password = aConfig[:site_password]
|
16
|
+
|
17
|
+
@dav = Net::DAV.new(MiscUtils.append_slash(@server_path), :curl => false)
|
18
|
+
@dav.verify_server = false
|
19
|
+
@dav.credentials(site_username,site_password)
|
20
|
+
@deploy_status_file = '/content/.deploy-status.txt'
|
21
|
+
end
|
22
|
+
|
23
|
+
DAV_METHODS = [:find]
|
24
|
+
|
25
|
+
def method_missing(sym, *args, &block)
|
26
|
+
if @dav && DAV_METHODS.include?(sym)
|
27
|
+
@dav.send sym, *args, &block
|
28
|
+
else
|
29
|
+
super
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def full_path(aRelativePath)
|
34
|
+
File.join(@server_path, URI.escape(aRelativePath))
|
35
|
+
end
|
36
|
+
|
37
|
+
def ls(aPath=nil,aRecursive=false)
|
38
|
+
result = []
|
39
|
+
path = MiscUtils.append_slash(full_path(aPath||''))
|
40
|
+
@dav.find(path,:recursive=>aRecursive,:suppress_errors=>false) do | item |
|
41
|
+
result << item.url.to_s.bite(path)
|
42
|
+
end
|
43
|
+
result
|
44
|
+
end
|
45
|
+
|
46
|
+
def list_files(aPath=nil,aRecursive=false)
|
47
|
+
result = ls(aPath,aRecursive)
|
48
|
+
result.delete_if {|f| f.ends_with? '/'}
|
49
|
+
result
|
50
|
+
end
|
51
|
+
|
52
|
+
def get_string(aPath)
|
53
|
+
begin
|
54
|
+
@dav.get(full_path(aPath))
|
55
|
+
rescue Net::HTTPServerException => e
|
56
|
+
e.response.is_a?(Net::HTTPNotFound) ? nil : raise
|
57
|
+
rescue Net::HTTPError => e
|
58
|
+
e.message.index('404') ? nil : raise
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def put_string(aPath,aString)
|
63
|
+
@dav.put_string(full_path(aPath),aString)
|
64
|
+
end
|
65
|
+
|
66
|
+
def ensure_folder_path(aPath)
|
67
|
+
path_parts = aPath.bite('/').chomp('/').split('/')
|
68
|
+
last_part = path_parts.length-1
|
69
|
+
existing_part = nil
|
70
|
+
last_part.downto(0) do |i|
|
71
|
+
existing_part = i if !existing_part && exists?(path = '/'+path_parts[0..i].join('/'))
|
72
|
+
end
|
73
|
+
(existing_part ? existing_part+1 : 0).upto(last_part) do |i|
|
74
|
+
mkdir('/'+path_parts[0..i].join('/'))
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def delete(aPath)
|
79
|
+
begin
|
80
|
+
@dav.delete(full_path(aPath))
|
81
|
+
rescue Net::HTTPServerException => e
|
82
|
+
e.response.is_a?(Net::HTTPNotFound) ? nil : raise
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def deploy_status
|
87
|
+
s = get_string(deploy_status_file)
|
88
|
+
s ? JSON.parse(s) : nil
|
89
|
+
end
|
90
|
+
|
91
|
+
def deploy_status=(aObject)
|
92
|
+
if aObject
|
93
|
+
s = JSON.generate(aObject)
|
94
|
+
put_string(deploy_status_file,s)
|
95
|
+
else
|
96
|
+
delete deploy_status_file
|
97
|
+
end
|
98
|
+
aObject
|
99
|
+
end
|
100
|
+
|
101
|
+
def put_file(aLocalFile, aRemotePath, aEnsureFolder=true)
|
102
|
+
s = MiscUtils.string_from_file(aLocalFile)
|
103
|
+
ensure_folder_path(File.dirname(aRemotePath)) if aEnsureFolder
|
104
|
+
put_string(aRemotePath,s)
|
105
|
+
end
|
106
|
+
|
107
|
+
def get_file(aRemotePath, aLocalFile)
|
108
|
+
s = get_string(aRemotePath)
|
109
|
+
MiscUtils.string_to_file(s,aLocalFile)
|
110
|
+
end
|
111
|
+
|
112
|
+
def upload_files(aLocalDir,aFiles,aFromPath=nil,aToPath=nil)
|
113
|
+
aFiles.each do |f|
|
114
|
+
to = f
|
115
|
+
to = MiscUtils.path_rebase(to,aFromPath,aToPath) if aFromPath && aToPath
|
116
|
+
put_file(File.join(aLocalDir,f),to)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def delete_files(aPaths,aFromPath=nil,aToPath=nil)
|
121
|
+
if (aFromPath && aToPath)
|
122
|
+
aPaths.each do |p|
|
123
|
+
delete(MiscUtils.path_rebase(p,aFromPath,aToPath))
|
124
|
+
end
|
125
|
+
else
|
126
|
+
aPaths.each do |p|
|
127
|
+
delete(p)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
def exists?(aPath)
|
133
|
+
@dav.exists? full_path(aPath)
|
134
|
+
end
|
135
|
+
|
136
|
+
def mkdir(aPath)
|
137
|
+
@dav.mkdir full_path(aPath)
|
138
|
+
end
|
139
|
+
|
140
|
+
end
|
141
|
+
end
|