designshell 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. data/.gitignore +18 -0
  2. data/.idea/.name +1 -0
  3. data/.idea/.rakeTasks +7 -0
  4. data/.idea/codeStyleSettings.xml +13 -0
  5. data/.idea/compiler.xml +25 -0
  6. data/.idea/copyright/profiles_settings.xml +5 -0
  7. data/.idea/encodings.xml +5 -0
  8. data/.idea/misc.xml +11 -0
  9. data/.idea/modules.xml +11 -0
  10. data/.idea/scopes/scope_settings.xml +5 -0
  11. data/.idea/vcs.xml +9 -0
  12. data/Gemfile +2 -0
  13. data/Gemfile.lock +196 -0
  14. data/LICENSE +22 -0
  15. data/README.md +35 -0
  16. data/README.rdoc +6 -0
  17. data/Rakefile +46 -0
  18. data/bin/designshelld.example.sh +5 -0
  19. data/bin/designshelld.example2.sh +3 -0
  20. data/bin/designshellserver +22 -0
  21. data/bin/ds +177 -0
  22. data/designshell.gemspec +40 -0
  23. data/designshell.iml +84 -0
  24. data/designshell.rdoc +5 -0
  25. data/features/designshell.feature +8 -0
  26. data/features/step_definitions/designshell_steps.rb +6 -0
  27. data/features/support/env.rb +15 -0
  28. data/lib/buzzcore_mods.rb +19 -0
  29. data/lib/designshell/context.rb +48 -0
  30. data/lib/designshell/core.rb +78 -0
  31. data/lib/designshell/deploy_plan.rb +40 -0
  32. data/lib/designshell/key_chain.rb +40 -0
  33. data/lib/designshell/repo.rb +112 -0
  34. data/lib/designshell/repo_server.rb +25 -0
  35. data/lib/designshell/site_client.rb +141 -0
  36. data/lib/designshell/utils.rb +18 -0
  37. data/lib/designshell/version.rb +3 -0
  38. data/lib/designshell.rb +19 -0
  39. data/lib/designshellserver/command.rb +180 -0
  40. data/lib/designshellserver/core.rb +41 -0
  41. data/lib/designshellserver.rb +17 -0
  42. data/spec/KeyChain_spec.rb +94 -0
  43. data/spec/RepoServer_spec.rb +54 -0
  44. data/spec/Repo_spec.rb +105 -0
  45. data/spec/build_spec.rb +29 -0
  46. data/spec/client_to_server_spec.rb +111 -0
  47. data/spec/designshell_context_spec.rb +18 -0
  48. data/spec/designshell_core_spec.rb +45 -0
  49. data/spec/rspec_helper.rb +8 -0
  50. data/spec/server/deploy_spec.rb +210 -0
  51. data/spec/server/dummy_spec.rb +52 -0
  52. data/spec/site_client_spec.rb +90 -0
  53. data/test/default_test.rb +14 -0
  54. data/test/test_helper.rb +9 -0
  55. data/testmart.iml +9 -0
  56. metadata +390 -0
@@ -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,5 @@
1
+ = designshell
2
+
3
+ Generate this with
4
+ ds rdoc
5
+ After you have described your command line interface
@@ -0,0 +1,8 @@
1
+ Feature: My bootstrapped app kinda works
2
+ In order to get going on coding my awesome app
3
+ I want to have aruba and cucumber setup
4
+ So I don't have to do it myself
5
+
6
+ Scenario: App just runs
7
+ When I get help for "ds"
8
+ Then the exit status should be 0
@@ -0,0 +1,6 @@
1
+ When /^I get help for "([^"]*)"$/ do |app_name|
2
+ @app_name = app_name
3
+ step %(I run `#{app_name} help`)
4
+ end
5
+
6
+ # Add more step definitions here
@@ -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