pivotal-piston 1.9.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (96) hide show
  1. data/.gitignore +8 -0
  2. data/History.txt +11 -0
  3. data/License.txt +20 -0
  4. data/Manifest.txt +85 -0
  5. data/README.txt +136 -0
  6. data/Rakefile +4 -0
  7. data/bin/piston +5 -0
  8. data/config/hoe.rb +79 -0
  9. data/config/requirements.rb +18 -0
  10. data/lib/piston.rb +18 -0
  11. data/lib/piston/cli.rb +315 -0
  12. data/lib/piston/commands.rb +4 -0
  13. data/lib/piston/commands/base.rb +44 -0
  14. data/lib/piston/commands/import.rb +42 -0
  15. data/lib/piston/commands/info.rb +14 -0
  16. data/lib/piston/commands/lock_unlock.rb +21 -0
  17. data/lib/piston/commands/update.rb +29 -0
  18. data/lib/piston/git.rb +12 -0
  19. data/lib/piston/git/client.rb +77 -0
  20. data/lib/piston/git/commit.rb +74 -0
  21. data/lib/piston/git/repository.rb +63 -0
  22. data/lib/piston/git/working_copy.rb +86 -0
  23. data/lib/piston/repository.rb +57 -0
  24. data/lib/piston/revision.rb +53 -0
  25. data/lib/piston/svn.rb +14 -0
  26. data/lib/piston/svn/client.rb +88 -0
  27. data/lib/piston/svn/repository.rb +67 -0
  28. data/lib/piston/svn/revision.rb +74 -0
  29. data/lib/piston/svn/working_copy.rb +108 -0
  30. data/lib/piston/version.rb +9 -0
  31. data/lib/piston/working_copy.rb +183 -0
  32. data/lib/subclass_responsibility_error.rb +2 -0
  33. data/log/.gitignore +0 -0
  34. data/samples/common.rb +19 -0
  35. data/samples/import_git_git.rb +39 -0
  36. data/samples/import_git_svn.rb +36 -0
  37. data/samples/import_svn_git.rb +29 -0
  38. data/samples/import_svn_svn.rb +24 -0
  39. data/script/destroy +14 -0
  40. data/script/generate +14 -0
  41. data/script/txt2html +74 -0
  42. data/setup.rb +1585 -0
  43. data/tasks/deployment.rake +34 -0
  44. data/tasks/environment.rake +7 -0
  45. data/tasks/samples.rake +6 -0
  46. data/tasks/test.rake +69 -0
  47. data/tasks/website.rake +17 -0
  48. data/test/integration/test_git_git.rb +99 -0
  49. data/test/integration/test_git_svn.rb +121 -0
  50. data/test/integration/test_import_svn_git.rb +47 -0
  51. data/test/integration/test_import_svn_svn.rb +38 -0
  52. data/test/integration_helpers.rb +33 -0
  53. data/test/test_helper.rb +83 -0
  54. data/test/unit/git/commit/test_checkout.rb +31 -0
  55. data/test/unit/git/commit/test_each.rb +30 -0
  56. data/test/unit/git/commit/test_rememberance.rb +21 -0
  57. data/test/unit/git/commit/test_validation.rb +34 -0
  58. data/test/unit/git/repository/test_at.rb +23 -0
  59. data/test/unit/git/repository/test_basename.rb +12 -0
  60. data/test/unit/git/repository/test_branchanme.rb +15 -0
  61. data/test/unit/git/repository/test_guessing.rb +32 -0
  62. data/test/unit/git/working_copy/test_copying.rb +25 -0
  63. data/test/unit/git/working_copy/test_creation.rb +22 -0
  64. data/test/unit/git/working_copy/test_existence.rb +18 -0
  65. data/test/unit/git/working_copy/test_finalization.rb +15 -0
  66. data/test/unit/git/working_copy/test_guessing.rb +35 -0
  67. data/test/unit/git/working_copy/test_rememberance.rb +21 -0
  68. data/test/unit/svn/repository/test_at.rb +19 -0
  69. data/test/unit/svn/repository/test_basename.rb +24 -0
  70. data/test/unit/svn/repository/test_guessing.rb +45 -0
  71. data/test/unit/svn/revision/test_checkout.rb +28 -0
  72. data/test/unit/svn/revision/test_each.rb +22 -0
  73. data/test/unit/svn/revision/test_rememberance.rb +38 -0
  74. data/test/unit/svn/revision/test_validation.rb +50 -0
  75. data/test/unit/svn/working_copy/test_copying.rb +26 -0
  76. data/test/unit/svn/working_copy/test_creation.rb +16 -0
  77. data/test/unit/svn/working_copy/test_existence.rb +23 -0
  78. data/test/unit/svn/working_copy/test_externals.rb +56 -0
  79. data/test/unit/svn/working_copy/test_finalization.rb +17 -0
  80. data/test/unit/svn/working_copy/test_guessing.rb +18 -0
  81. data/test/unit/svn/working_copy/test_merging.rb +47 -0
  82. data/test/unit/svn/working_copy/test_rememberance.rb +26 -0
  83. data/test/unit/test_info.rb +37 -0
  84. data/test/unit/test_lock_unlock.rb +47 -0
  85. data/test/unit/test_repository.rb +51 -0
  86. data/test/unit/test_revision.rb +31 -0
  87. data/test/unit/working_copy/test_guessing.rb +35 -0
  88. data/test/unit/working_copy/test_info.rb +14 -0
  89. data/test/unit/working_copy/test_rememberance.rb +42 -0
  90. data/test/unit/working_copy/test_validate.rb +63 -0
  91. data/website/index.html +11 -0
  92. data/website/index.txt +39 -0
  93. data/website/javascripts/rounded_corners_lite.inc.js +285 -0
  94. data/website/stylesheets/screen.css +138 -0
  95. data/website/template.rhtml +48 -0
  96. metadata +244 -0
@@ -0,0 +1,4 @@
1
+ dir = File.dirname(__FILE__)
2
+ Dir["#{dir}/commands/**/*.rb"].each do |f|
3
+ require f.gsub("#{File.expand_path("#{File.dirname(f)}/../..")}/", "")
4
+ end
@@ -0,0 +1,44 @@
1
+ module Piston
2
+ module Commands
3
+ class Base
4
+ class << self
5
+ def logger
6
+ @@logger ||= Log4r::Logger["main"]
7
+ end
8
+ end
9
+
10
+ attr_reader :options
11
+
12
+ def initialize(options={})
13
+ @options = options
14
+ logger.debug {"#{self.class.name} with options #{options.inspect}"}
15
+ end
16
+
17
+ def verbose
18
+ @options[:verbose]
19
+ end
20
+
21
+ def force
22
+ @options[:force]
23
+ end
24
+
25
+ def quiet
26
+ @options[:quiet]
27
+ end
28
+
29
+ def logger
30
+ self.class.logger
31
+ end
32
+
33
+ def guess_wc(wcdir)
34
+ Piston::WorkingCopy.guess(wcdir)
35
+ end
36
+
37
+ def working_copy!(wcdir)
38
+ wc = guess_wc(wcdir)
39
+ wc.validate!
40
+ wc
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,42 @@
1
+ require "piston/commands/base"
2
+
3
+ module Piston
4
+ module Commands
5
+ class Import < Piston::Commands::Base
6
+ attr_reader :options
7
+
8
+ def repository_type
9
+ options[:repository_type]
10
+ end
11
+
12
+ def select_repository(repository_url)
13
+ if repository_type then
14
+ logger.info {"Forced repository type to #{repository_type}"}
15
+ repository_class_name = "Piston::#{repository_type.downcase.capitalize}::Repository"
16
+ repository_class = repository_class_name.constantize
17
+ repository_class.new(repository_url)
18
+ else
19
+ logger.info {"Guessing the repository type"}
20
+ Piston::Repository.guess(repository_url)
21
+ end
22
+ end
23
+
24
+ def run(repository_url, target_revision, wcdir)
25
+ repository = select_repository(repository_url)
26
+ revision = repository.at(target_revision)
27
+
28
+ wcdir = File.expand_path(wcdir.nil? ? repository.basename : wcdir)
29
+ logger.info {"Guessing the working copy type"}
30
+ logger.debug {"repository_url: #{repository_url.inspect}, target_revision: #{target_revision.inspect}, wcdir: #{wcdir.inspect}"}
31
+ working_copy = guess_wc(wcdir)
32
+
33
+ if working_copy.exist? && !force then
34
+ logger.fatal "Path #{working_copy} already exists and --force not given. Aborting..."
35
+ abort
36
+ end
37
+
38
+ working_copy.import(revision, options[:lock])
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,14 @@
1
+ require "piston/commands/base"
2
+
3
+ module Piston
4
+ module Commands
5
+ class Info < Piston::Commands::Base
6
+ attr_reader :options
7
+
8
+ def run(wcdir)
9
+ working_copy = working_copy!(wcdir)
10
+ working_copy.info.to_yaml
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,21 @@
1
+ require "piston/commands/base"
2
+
3
+ module Piston
4
+ module Commands
5
+ class LockUnlock < Piston::Commands::Base
6
+ attr_reader :options
7
+
8
+ def run(wcdir, lock)
9
+ working_copy = working_copy!(wcdir)
10
+
11
+ values = working_copy.recall
12
+ values["lock"] = lock
13
+ working_copy.remember(values, values["handler"])
14
+ working_copy.finalize
15
+
16
+ text = lock ? "Locked" : "Unlocked"
17
+ logger.info "#{text} #{working_copy} against automatic updates"
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,29 @@
1
+ require "piston/commands/base"
2
+
3
+ module Piston
4
+ module Commands
5
+ class Update < Piston::Commands::Base
6
+ # +wcdir+ is the working copy we're going to change.
7
+ # +to+ is the new target revision we want to be at after update returns.
8
+ def run(wcdir, to)
9
+ working_copy = working_copy!(wcdir)
10
+
11
+ logger.debug {"Recalling previously saved values"}
12
+ values = working_copy.recall
13
+
14
+ repository_class = values["repository_class"]
15
+ repository_url = values["repository_url"]
16
+ repository = repository_class.constantize.new(repository_url)
17
+ from_revision = repository.at(values["handler"])
18
+ to_revision = repository.at(to)
19
+
20
+ logger.debug {"Validating that #{from_revision} exists and is capable of performing the update"}
21
+ from_revision.validate!
22
+
23
+ logger.info {"Updating from #{from_revision} to #{to_revision}"}
24
+
25
+ working_copy.update(to_revision, options[:lock])
26
+ end
27
+ end
28
+ end
29
+ end
data/lib/piston/git.rb ADDED
@@ -0,0 +1,12 @@
1
+ require "piston/git/client"
2
+ require "piston/git/repository"
3
+ require "piston/git/commit"
4
+ require "piston/git/working_copy"
5
+
6
+ module Piston
7
+ module Git
8
+ URL = "url"
9
+ COMMIT = "commit"
10
+ BRANCH = "branch"
11
+ end
12
+ end
@@ -0,0 +1,77 @@
1
+ require "singleton"
2
+
3
+ module Piston
4
+ module Git
5
+ class Client
6
+ include Singleton
7
+
8
+ class CommandError < RuntimeError; end
9
+ class Failed < CommandError; end
10
+ class BadCommand < CommandError; end
11
+
12
+ def logger
13
+ @logger ||= Log4r::Logger["handler::client"]
14
+ end
15
+
16
+ def out_logger
17
+ @out_logger ||= Log4r::Logger["handler::client::out"]
18
+ end
19
+
20
+ def git(*args)
21
+ run_cmd :git, *args
22
+ end
23
+
24
+ private
25
+ def run_cmd(executable, *args)
26
+ args.collect! {|arg| arg =~ /\s|\*|\?|"|\n|\r/ ? %Q('#{arg}') : arg}
27
+ args.collect! {|arg| arg ? arg : '""'}
28
+ cmd = %Q|#{executable} #{args.join(' ')}|
29
+ logger.debug {"> " + cmd}
30
+
31
+ original_language = ENV["LANGUAGE"]
32
+ begin
33
+ ENV["LANGUAGE"] = "C"
34
+ value = run_real(cmd)
35
+ out_logger.info {"< " + value} unless (value || "").strip.empty?
36
+ return value
37
+ ensure
38
+ ENV["LANGUAGE"] = original_language
39
+ end
40
+ end
41
+
42
+ begin
43
+ raise LoadError, "Not implemented on Win32 machines" if RUBY_PLATFORM =~ /mswin32/
44
+
45
+ begin
46
+ require "rubygems"
47
+ rescue LoadError
48
+ # NOP -- attempt to load without Rubygems
49
+ end
50
+
51
+ require "open4"
52
+
53
+ def run_real(cmd)
54
+ begin
55
+ pid, stdin, stdout, stderr = Open4::popen4(cmd)
56
+ _, cmdstatus = Process.waitpid2(pid)
57
+ return stdout.read if cmd =~ /status/ && cmdstatus.exitstatus == 1
58
+ raise CommandError, "#{cmd.inspect} exited with status: #{cmdstatus.exitstatus}\n#{stderr.read}" unless cmdstatus.success?
59
+ return stdout.read
60
+ rescue Errno::ENOENT
61
+ raise BadCommand, cmd.inspect
62
+ end
63
+ end
64
+
65
+ rescue LoadError
66
+ # On platforms where open4 is unavailable, we fallback to running using
67
+ # the backtick method of Kernel.
68
+ def run_real(cmd)
69
+ out = `#{cmd}`
70
+ raise BadCommand, cmd.inspect if $?.exitstatus == 127
71
+ raise Failed, "#{cmd.inspect} exited with status: #{$?.exitstatus}" unless $?.success?
72
+ out
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,74 @@
1
+ require "piston/git/client"
2
+ require "piston/revision"
3
+ require "fileutils"
4
+
5
+ module Piston
6
+ module Git
7
+ class Commit < Piston::Revision
8
+ class InvalidCommit < RuntimeError; end
9
+ class Gone < InvalidCommit; end
10
+
11
+ alias_method :commit, :revision
12
+ attr_reader :sha1
13
+
14
+ def client
15
+ @client ||= Piston::Git::Client.instance
16
+ end
17
+
18
+ def git(*args)
19
+ client.git(*args)
20
+ end
21
+
22
+ def recalled_commit_id
23
+ recalled_values[Piston::Git::COMMIT]
24
+ end
25
+
26
+ def validate!
27
+ begin
28
+ data = git("ls-remote", @repository.url)
29
+ self
30
+ rescue Piston::Git::Client::CommandError
31
+ raise Piston::Git::Commit::Gone, "Repository at #{@repository.url} does not exist anymore"
32
+ end
33
+ end
34
+
35
+ def name
36
+ commit[0,7]
37
+ end
38
+
39
+ def branch_name
40
+ "my-#{commit}"
41
+ end
42
+
43
+ def checkout_to(dir)
44
+ super
45
+ git(:clone, repository.url, @dir)
46
+ Dir.chdir(@dir) do
47
+ logger.debug {"in dir #{@dir}"}
48
+ git(:checkout, "-b", branch_name, commit)
49
+ response = git(:log, "-n", "1")
50
+ @sha1 = $1 if response =~ /commit\s+([a-f\d]{40})/i
51
+ end
52
+
53
+ def remember_values
54
+ { Piston::Git::COMMIT => @sha1, Piston::Git::BRANCH => commit }
55
+ end
56
+
57
+ def each
58
+ raise ArgumentError, "Never cloned + checked out" if @dir.nil?
59
+ @dir.find do |path|
60
+ Find.prune if path.to_s =~ %r{/[.]git}
61
+ next if @dir == path
62
+ next if File.directory?(path)
63
+ yield path.relative_path_from(@dir)
64
+ end
65
+ end
66
+
67
+ def copy_to(relpath, abspath)
68
+ Pathname.new(abspath).dirname.mkpath
69
+ FileUtils.cp(@dir + relpath, abspath)
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,63 @@
1
+ require "piston/git/commit"
2
+ require "uri"
3
+
4
+ module Piston
5
+ module Git
6
+ class Repository < Piston::Repository
7
+ Piston::Repository.add_handler self
8
+
9
+ class << self
10
+ def understands_url?(url)
11
+ uri = URI.parse(url) rescue nil
12
+ return true if uri && %w(git).include?(uri.scheme)
13
+
14
+ begin
15
+ response = git("ls-remote", "--heads", url.sub(/\?.+$/, ""))
16
+ return false if response.nil? || response.strip.chomp.empty?
17
+ !!(response =~ /[a-f\d]{40}\s/)
18
+ rescue Piston::Git::Client::CommandError
19
+ false
20
+ end
21
+ end
22
+
23
+ def client
24
+ @@client ||= Piston::Git::Client.instance
25
+ end
26
+
27
+ def git(*args)
28
+ client.git(*args)
29
+ end
30
+
31
+ def repository_type
32
+ 'git'
33
+ end
34
+ end
35
+
36
+ attr_reader :branchname
37
+
38
+ def initialize(url)
39
+ @branchname = url.split("?")[1]
40
+ super(url.sub(/\?.+$/, ""))
41
+ end
42
+
43
+ def git(*args)
44
+ self.class.git(*args)
45
+ end
46
+
47
+ def at(commit)
48
+ case commit
49
+ when Hash
50
+ Piston::Git::Commit.new(self, commit[Piston::Git::COMMIT])
51
+ when :head
52
+ Piston::Git::Commit.new(self, "HEAD")
53
+ else
54
+ Piston::Git::Commit.new(self, commit)
55
+ end
56
+ end
57
+
58
+ def basename
59
+ self.url.split("/").last.sub(".git", "")
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,86 @@
1
+ require "piston/working_copy"
2
+ require "piston/git/client"
3
+
4
+ module Piston
5
+ module Git
6
+ class WorkingCopy < Piston::WorkingCopy
7
+ # Register ourselves as a handler for working copies
8
+ Piston::WorkingCopy.add_handler self
9
+
10
+ class << self
11
+ def understands_dir?(dir)
12
+ path = dir
13
+ begin
14
+ begin
15
+ logger.debug {"git status on #{path}"}
16
+ Dir.chdir(path) do
17
+ response = git(:status)
18
+ return true if response =~ /# On branch /
19
+ end
20
+ rescue Errno::ENOENT
21
+ # NOP, we assume this is simply because the folder hasn't been created yet
22
+ path = path.parent
23
+ retry unless path.to_s == "/"
24
+ return false
25
+ end
26
+ rescue Piston::Git::Client::BadCommand
27
+ # NOP, as we return false below
28
+ rescue Piston::Git::Client::CommandError
29
+ # This is certainly not a Git repository
30
+ false
31
+ end
32
+
33
+ false
34
+ end
35
+
36
+ def client
37
+ @@client ||= Piston::Git::Client.instance
38
+ end
39
+
40
+ def git(*args)
41
+ client.git(*args)
42
+ end
43
+ end
44
+
45
+ def git(*args)
46
+ self.class.git(*args)
47
+ end
48
+
49
+ def create
50
+ path.mkpath rescue nil
51
+ end
52
+
53
+ def exist?
54
+ path.directory?
55
+ end
56
+
57
+ def finalize
58
+ Dir.chdir(path) { git(:add, ".") }
59
+ end
60
+
61
+ protected
62
+ def do_update(to, lock)
63
+ puts "tmpdir: #{to.dir}"
64
+ puts "exist? #{to.dir.exist?}"
65
+ puts "file? #{to.dir.file?}"
66
+ puts "directory? #{to.dir.directory?}"
67
+ path.children.reject {|item| ['.git', '.piston.yml'].include?(item.basename.to_s)}.each do |item|
68
+ puts "rm -rf #{item}"
69
+ FileUtils.rm_rf(item)
70
+ end
71
+ to.dir.children.reject {|item| item.basename.to_s == '.git'}.each do |item|
72
+ puts "cp -r #{item} #{path}"
73
+ FileUtils.cp_r(item, path)
74
+ end
75
+ Dir.chdir(path) do
76
+ repository = to.repository
77
+ remember(
78
+ {:repository_url => repository.url, :lock => lock, :repository_class => repository.class.name},
79
+ to.remember_values
80
+ )
81
+ git(:add, ".")
82
+ end
83
+ end
84
+ end
85
+ end
86
+ end