designshell 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.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
|