piston 1.4.0 → 2.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (85) hide show
  1. data/History.txt +24 -0
  2. data/License.txt +20 -0
  3. data/Manifest.txt +109 -0
  4. data/{README → README.txt} +14 -10
  5. data/VERSION.yml +4 -0
  6. data/bin/piston +3 -8
  7. data/lib/piston/cli.rb +121 -0
  8. data/lib/piston/commands/base.rb +44 -0
  9. data/lib/piston/commands/convert.rb +23 -71
  10. data/lib/piston/commands/diff.rb +14 -46
  11. data/lib/piston/commands/import.rb +48 -57
  12. data/lib/piston/commands/info.rb +24 -0
  13. data/lib/piston/commands/lock_unlock.rb +26 -0
  14. data/lib/piston/commands/status.rb +29 -54
  15. data/lib/piston/commands/update.rb +35 -122
  16. data/lib/piston/commands/upgrade.rb +26 -0
  17. data/lib/piston/commands.rb +4 -0
  18. data/lib/piston/git/client.rb +76 -0
  19. data/lib/piston/git/commit.rb +114 -0
  20. data/lib/piston/git/repository.rb +63 -0
  21. data/lib/piston/git/working_copy.rb +145 -0
  22. data/lib/piston/git.rb +13 -0
  23. data/lib/piston/repository.rb +61 -0
  24. data/lib/piston/revision.rb +83 -0
  25. data/lib/piston/svn/client.rb +88 -0
  26. data/lib/piston/svn/repository.rb +67 -0
  27. data/lib/piston/svn/revision.rb +112 -0
  28. data/lib/piston/svn/working_copy.rb +184 -0
  29. data/lib/piston/svn.rb +15 -0
  30. data/lib/piston/version.rb +9 -7
  31. data/lib/piston/working_copy.rb +334 -0
  32. data/lib/piston.rb +13 -64
  33. data/lib/subclass_responsibility_error.rb +2 -0
  34. data/test/integration_helpers.rb +36 -0
  35. data/test/spec_suite.rb +4 -0
  36. data/test/test_helper.rb +92 -0
  37. data/test/unit/git/commit/test_checkout.rb +31 -0
  38. data/test/unit/git/commit/test_each.rb +30 -0
  39. data/test/unit/git/commit/test_rememberance.rb +22 -0
  40. data/test/unit/git/commit/test_validation.rb +34 -0
  41. data/test/unit/git/repository/test_at.rb +23 -0
  42. data/test/unit/git/repository/test_basename.rb +12 -0
  43. data/test/unit/git/repository/test_branchanme.rb +15 -0
  44. data/test/unit/git/repository/test_guessing.rb +32 -0
  45. data/test/unit/git/working_copy/test_copying.rb +25 -0
  46. data/test/unit/git/working_copy/test_creation.rb +22 -0
  47. data/test/unit/git/working_copy/test_existence.rb +18 -0
  48. data/test/unit/git/working_copy/test_finalization.rb +15 -0
  49. data/test/unit/git/working_copy/test_guessing.rb +35 -0
  50. data/test/unit/git/working_copy/test_rememberance.rb +22 -0
  51. data/test/unit/svn/repository/test_at.rb +19 -0
  52. data/test/unit/svn/repository/test_basename.rb +24 -0
  53. data/test/unit/svn/repository/test_guessing.rb +45 -0
  54. data/test/unit/svn/revision/test_checkout.rb +28 -0
  55. data/test/unit/svn/revision/test_each.rb +22 -0
  56. data/test/unit/svn/revision/test_rememberance.rb +38 -0
  57. data/test/unit/svn/revision/test_validation.rb +50 -0
  58. data/test/unit/svn/working_copy/test_copying.rb +26 -0
  59. data/test/unit/svn/working_copy/test_creation.rb +16 -0
  60. data/test/unit/svn/working_copy/test_existence.rb +23 -0
  61. data/test/unit/svn/working_copy/test_externals.rb +56 -0
  62. data/test/unit/svn/working_copy/test_finalization.rb +17 -0
  63. data/test/unit/svn/working_copy/test_guessing.rb +18 -0
  64. data/test/unit/svn/working_copy/test_rememberance.rb +26 -0
  65. data/test/unit/test_info.rb +37 -0
  66. data/test/unit/test_lock_unlock.rb +47 -0
  67. data/test/unit/test_repository.rb +51 -0
  68. data/test/unit/test_revision.rb +31 -0
  69. data/test/unit/working_copy/test_guessing.rb +35 -0
  70. data/test/unit/working_copy/test_info.rb +14 -0
  71. data/test/unit/working_copy/test_rememberance.rb +42 -0
  72. data/test/unit/working_copy/test_validate.rb +63 -0
  73. metadata +132 -31
  74. data/CHANGELOG +0 -81
  75. data/LICENSE +0 -19
  76. data/Rakefile +0 -63
  77. data/contrib/piston +0 -43
  78. data/lib/core_ext/range.rb +0 -5
  79. data/lib/core_ext/string.rb +0 -9
  80. data/lib/piston/command.rb +0 -68
  81. data/lib/piston/command_error.rb +0 -6
  82. data/lib/piston/commands/lock.rb +0 -30
  83. data/lib/piston/commands/switch.rb +0 -139
  84. data/lib/piston/commands/unlock.rb +0 -29
  85. data/lib/transat/parser.rb +0 -189
data/History.txt ADDED
@@ -0,0 +1,24 @@
1
+ == 2.0.1 2009-04-01
2
+
3
+ * Finished testing on Ruby 1.9.1.
4
+ * Released new website.
5
+
6
+ == 1.9.5 2008-11-12
7
+
8
+ * Merged everything that was relevant from the community.
9
+ * Thanks to scambra for fixing many problems with piston update.
10
+
11
+ == 1.9.4
12
+
13
+ * Thanks to scambra for fixing lock/unlock errors.
14
+ * Thanks to Geoffrey Grosenbach (topfunky), piston has a gemspec for use on GitHub.
15
+ * Thanks to Brian Takita (btakita), piston update with a Git repository works!
16
+ * Thanks to mattknox and scambra for manifest updates.
17
+ * Thanks to Marcos Tapajós (tapajos) for many small improvements.
18
+
19
+ == 1.9.3 2008-06-03
20
+
21
+ * Import git branches using --revision origin/BRANCH_NAME, or a tag
22
+ using --revision TAG_NAME, or even a specific commit using
23
+ --revision COMMIT_ID. In fact, use a committish and you'll be fine,
24
+ even HEAD^3.
data/License.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2006-2008 François Beausoleil <francois@teksol.info>
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Manifest.txt ADDED
@@ -0,0 +1,109 @@
1
+ .gitignore
2
+ bin/piston
3
+ config/hoe.rb
4
+ config/requirements.rb
5
+ features/import_to_git.feature
6
+ features/import_to_svn.feature
7
+ features/step_definitions/repository.rb
8
+ features/support/env.rb
9
+ features/support/svn.rb
10
+ features/update_to_git.feature
11
+ features/update_to_svn.feature
12
+ History.txt
13
+ lib/piston/cli.rb
14
+ lib/piston/commands/base.rb
15
+ lib/piston/commands/convert.rb
16
+ lib/piston/commands/import.rb
17
+ lib/piston/commands/info.rb
18
+ lib/piston/commands/lock_unlock.rb
19
+ lib/piston/commands/status.rb
20
+ lib/piston/commands/update.rb
21
+ lib/piston/commands/upgrade.rb
22
+ lib/piston/commands.rb
23
+ lib/piston/git/client.rb
24
+ lib/piston/git/commit.rb
25
+ lib/piston/git/repository.rb
26
+ lib/piston/git/working_copy.rb
27
+ lib/piston/git.rb
28
+ lib/piston/repository.rb
29
+ lib/piston/revision.rb
30
+ lib/piston/svn/client.rb
31
+ lib/piston/svn/repository.rb
32
+ lib/piston/svn/revision.rb
33
+ lib/piston/svn/working_copy.rb
34
+ lib/piston/svn.rb
35
+ lib/piston/version.rb
36
+ lib/piston/working_copy.rb
37
+ lib/piston.rb
38
+ lib/subclass_responsibility_error.rb
39
+ License.txt
40
+ log/.gitignore
41
+ Manifest.txt
42
+ piston.gemspec
43
+ Rakefile
44
+ README.txt
45
+ samples/common.rb
46
+ samples/import_git_git.rb
47
+ samples/import_git_svn.rb
48
+ samples/import_svn_git.rb
49
+ samples/import_svn_svn.rb
50
+ script/destroy
51
+ script/generate
52
+ script/txt2html
53
+ setup.rb
54
+ tasks/deployment.rake
55
+ tasks/environment.rake
56
+ tasks/manifest.rake
57
+ tasks/samples.rake
58
+ tasks/test.rake
59
+ tasks/website.rake
60
+ test/integration/test_git_git.rb
61
+ test/integration/test_git_svn.rb
62
+ test/integration/test_import_svn_git.rb
63
+ test/integration/test_svn_svn.rb
64
+ test/integration_helpers.rb
65
+ test/spec_suite.rb
66
+ test/test_helper.rb
67
+ test/unit/git/commit/test_checkout.rb
68
+ test/unit/git/commit/test_each.rb
69
+ test/unit/git/commit/test_rememberance.rb
70
+ test/unit/git/commit/test_validation.rb
71
+ test/unit/git/repository/test_at.rb
72
+ test/unit/git/repository/test_basename.rb
73
+ test/unit/git/repository/test_branchanme.rb
74
+ test/unit/git/repository/test_guessing.rb
75
+ test/unit/git/working_copy/test_copying.rb
76
+ test/unit/git/working_copy/test_creation.rb
77
+ test/unit/git/working_copy/test_existence.rb
78
+ test/unit/git/working_copy/test_finalization.rb
79
+ test/unit/git/working_copy/test_guessing.rb
80
+ test/unit/git/working_copy/test_rememberance.rb
81
+ test/unit/svn/repository/test_at.rb
82
+ test/unit/svn/repository/test_basename.rb
83
+ test/unit/svn/repository/test_guessing.rb
84
+ test/unit/svn/revision/test_checkout.rb
85
+ test/unit/svn/revision/test_each.rb
86
+ test/unit/svn/revision/test_rememberance.rb
87
+ test/unit/svn/revision/test_validation.rb
88
+ test/unit/svn/working_copy/test_copying.rb
89
+ test/unit/svn/working_copy/test_creation.rb
90
+ test/unit/svn/working_copy/test_existence.rb
91
+ test/unit/svn/working_copy/test_externals.rb
92
+ test/unit/svn/working_copy/test_finalization.rb
93
+ test/unit/svn/working_copy/test_guessing.rb
94
+ test/unit/svn/working_copy/test_rememberance.rb
95
+ test/unit/test_info.rb
96
+ test/unit/test_lock_unlock.rb
97
+ test/unit/test_repository.rb
98
+ test/unit/test_revision.rb
99
+ test/unit/working_copy/test_guessing.rb
100
+ test/unit/working_copy/test_info.rb
101
+ test/unit/working_copy/test_rememberance.rb
102
+ test/unit/working_copy/test_validate.rb
103
+ tmp/.gitignore
104
+ TODO
105
+ website/index.html
106
+ website/index.txt
107
+ website/javascripts/rounded_corners_lite.inc.js
108
+ website/stylesheets/screen.css
109
+ website/template.rhtml
@@ -3,6 +3,8 @@ This is similar to <tt>svn:externals</tt>, except you have a local copy of
3
3
  the files, which you can modify at will. As long as the changes are
4
4
  mergeable, you should have no problems.
5
5
 
6
+ Piston is Ruby 1.9.1 compatible.
7
+
6
8
  This tool has a similar purpose than svnmerge.py which you can find in the
7
9
  contrib/client-side folder of the main Subversion repository at
8
10
  http://svn.collab.net/repos/svn/trunk/contrib/client-side/svnmerge.py.
@@ -22,11 +24,22 @@ inside the cylinder." Piston forces the content of a remote repository
22
24
  location back into our own.
23
25
 
24
26
 
27
+ = Notes on 2.0
28
+
29
+ In the 1.0 era, Piston was exclusively geared towards Subversion repositories.
30
+ In early 2008, Git gained a lot of popularity among Ruby and Rails coders.
31
+ Piston was rewritten during that period to allow many repositories and working
32
+ copies to be used together.
33
+
34
+ The documentation still refers to Subversion throughout, but 2.0 allows any
35
+ repository to be used with any working copy.
36
+
37
+
25
38
  = Installation
26
39
 
27
40
  Nothing could be simpler:
28
41
 
29
- $ gem install --include-dependencies piston
42
+ $ gem install piston
30
43
 
31
44
 
32
45
  = Usage
@@ -123,12 +136,3 @@ repository than the one we checked out from originally.
123
136
  * <tt>piston:locked</tt>: The revision at which this folder is locked. If
124
137
  this property is set and non-blank, Piston will skip the folder with
125
138
  an appropriate message.
126
-
127
-
128
- = Dependencies
129
-
130
- Piston depends on the following libraries:
131
-
132
- * yaml
133
- * uri
134
- * fileutils
data/VERSION.yml ADDED
@@ -0,0 +1,4 @@
1
+ ---
2
+ :major: 2
3
+ :minor: 0
4
+ :patch: 1
data/bin/piston CHANGED
@@ -1,10 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
+ require "piston"
2
3
 
3
- begin
4
- require 'rubygems'
5
- rescue LoadError
6
- # no rubygems to load, so we fail silently
7
- end
8
-
9
- require 'piston'
10
- PistonCommandLineProcessor.parse_and_execute
4
+ # Chain to the real command-line client
5
+ require "piston/cli"
data/lib/piston/cli.rb ADDED
@@ -0,0 +1,121 @@
1
+ require "log4r"
2
+ require "activesupport"
3
+ require "piston/version"
4
+ require "optparse"
5
+
6
+ module Piston
7
+ class Cli
8
+ def self.start(args=ARGV)
9
+ options = {:lock => false, :force => false, :dry_run => false, :quiet => false, :verbose => 0}
10
+ opts = OptionParser.new do |opts|
11
+ opts.banner = "Usage: piston COMMAND [options]"
12
+ opts.version = Piston::VERSION::STRING
13
+
14
+ # Many!!!
15
+ opts.on("-r", "--revision REVISION", "Revision to operate on") do |r|
16
+ options[:revision] = r.to_i
17
+ end
18
+
19
+ opts.on("--commit TREEISH", "Commit to operate on") do |c|
20
+ options[:commit] = c
21
+ end
22
+
23
+ # Import
24
+ opts.on("--repository-type TYPE", [:git, :svn], "Force selection of a repository handler (git or svn)") do |type|
25
+ options[:repository_type] = type
26
+ end
27
+
28
+ # Import, Update and Switch
29
+ opts.on("--lock", "Lock down the revision against mass-updates") do
30
+ options[:lock] = true
31
+ end
32
+
33
+ opts.on("--show-updates", "Query the remote repository for out-of-dateness information") do
34
+ options[:show_updates] = true
35
+ end
36
+
37
+ # All
38
+ opts.on("--force", "Force the operation to go ahead") do
39
+ options[:force] = true
40
+ end
41
+
42
+ opts.on("--dry-run", "Run but do not change anything") do
43
+ options[:dry_run] = true
44
+ end
45
+
46
+ opts.on("-q", "--quiet", "Operate silently") do
47
+ options[:quiet] = true
48
+ end
49
+
50
+ opts.on("-v", "--verbose [LEVEL]", ("0".."5").to_a, "Increase verbosity (default 0)") do |level|
51
+ options[:verbose] = level.to_i || 1
52
+ end
53
+ end
54
+ opts.parse!(args)
55
+
56
+ if args.empty?
57
+ puts opts.help
58
+ exit 0
59
+ end
60
+
61
+ if options.has_key?(:revision) && options.has_key?(:commit) then
62
+ raise ArgumentError, "Only one of --revision or --commit can be given. Received both."
63
+ end
64
+
65
+ configure_logging(options)
66
+ command = Piston::Commands.const_get(args.shift.classify).new(options)
67
+ command.start(*args)
68
+ end
69
+
70
+ def self.configure_logging(options)
71
+ Log4r::Logger.root.level = Log4r::DEBUG
72
+
73
+ case options[:verbose]
74
+ when 0
75
+ main_level = Log4r::INFO
76
+ handler_level = Log4r::WARN
77
+ client_level = Log4r::WARN
78
+ client_out_level = Log4r::WARN
79
+ stdout_level = Log4r::INFO
80
+ when 1
81
+ main_level = Log4r::DEBUG
82
+ handler_level = Log4r::INFO
83
+ client_level = Log4r::WARN
84
+ client_out_level = Log4r::WARN
85
+ stdout_level = Log4r::DEBUG
86
+ when 2
87
+ main_level = Log4r::DEBUG
88
+ handler_level = Log4r::DEBUG
89
+ client_level = Log4r::INFO
90
+ client_out_level = Log4r::WARN
91
+ stdout_level = Log4r::DEBUG
92
+ when 3
93
+ main_level = Log4r::DEBUG
94
+ handler_level = Log4r::DEBUG
95
+ client_level = Log4r::DEBUG
96
+ client_out_level = Log4r::INFO
97
+ stdout_level = Log4r::DEBUG
98
+ when 4, 5
99
+ main_level = Log4r::DEBUG
100
+ handler_level = Log4r::DEBUG
101
+ client_level = Log4r::DEBUG
102
+ client_out_level = Log4r::DEBUG
103
+ stdout_level = Log4r::DEBUG
104
+ else
105
+ raise ArgumentError, "Did not expect verbosity to be outside 0..5: #{options[:verbose]}"
106
+ end
107
+
108
+ Log4r::Logger.new("main", main_level)
109
+ Log4r::Logger.new("handler", handler_level)
110
+ Log4r::Logger.new("handler::client", client_level)
111
+ Log4r::Logger.new("handler::client::out", client_out_level)
112
+
113
+ Log4r::StdoutOutputter.new("stdout", :level => stdout_level)
114
+
115
+ Log4r::Logger["main"].add "stdout"
116
+ Log4r::Logger["handler"].add "stdout"
117
+ end
118
+ end
119
+ end
120
+
121
+ Piston::Cli.start
@@ -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
@@ -1,80 +1,32 @@
1
- require "piston"
2
- require "piston/command"
3
- require "piston/commands/import"
1
+ require "piston/commands/base"
4
2
 
5
3
  module Piston
6
4
  module Commands
7
- class Convert < Piston::Command
8
- def run
9
- if args.empty? then
10
- svn(:propget, '--recursive', 'svn:externals').each_line do |line|
11
- next unless line =~ /^([^ ]+)\s-\s/
12
- args << $1
5
+ class Convert < Piston::Commands::Base
6
+ attr_reader :options
7
+
8
+ def run(targets)
9
+ targets = Array.new unless targets
10
+ wc = Piston::Svn::WorkingCopy.new(Dir.pwd)
11
+ importer = Piston::Commands::Import.new(options)
12
+ returning(Array.new) do |conversions|
13
+ wc.externals.each_pair do |dir, args|
14
+ next unless targets.empty? || targets.detect {|target| dir.to_s.include?(target.to_s) }
15
+ conversions << dir
16
+
17
+ logger.info "Importing #{dir.relative_path_from(wc.path)} from #{args[:url]}"
18
+ importer.run(args[:url], args[:revision], dir)
13
19
  end
14
- end
15
-
16
- return logging_stream.puts("No svn:externals defined in this folder or any of it's subfolders") if args.empty?
17
-
18
- args.each do |dir|
19
- externals = svn(:propget, 'svn:externals', dir)
20
- next skip_no_externals(dir) if externals.chomp.empty?
21
-
22
- operations = Array.new
23
- externals.each_line do |external|
24
- external.chomp!
25
- next if external.empty?
26
- next skip_no_match(external) unless external =~ /^([^ ]+)\s+(?:-r\s*(\d+)\s+)?(.*)$/
27
-
28
- local, revision, repos = $1, $2, $3
29
- lock = true if revision
30
- local_dir = File.join(dir, local)
31
- if File.exists?(local_dir)
32
- raise Piston::CommandError, "#{local_dir.inspect} is not a directory" unless File.directory?(local_dir)
33
- status = svn(:status, local_dir)
34
- raise Piston::CommandError, "#{local_dir.inspect} has local modifications:\n#{status}\nYour must revert or commit before trying again." unless status.empty?
35
- info = YAML::load(svn(:info, local_dir))
36
- revision = info['Last Changed Rev'] unless revision
37
- FileUtils.rm_rf(local_dir)
38
- end
39
20
 
40
- operations << [local_dir, revision, repos, lock]
41
- end
42
-
43
- operations.each do |local_dir, revision, repos, lock|
44
- logging_stream.puts "Importing '#{repos}' to #{local_dir} (-r #{revision || 'HEAD'}#{' locked' if lock})"
45
- import = Piston::Commands::Import.new([repos, local_dir], {})
46
- import.revision = revision
47
- import.verbose, import.quiet, import.logging_stream = self.verbose, self.quiet, self.logging_stream
48
- import.lock = lock
49
- import.run
50
- logging_stream.puts
51
- end
21
+ wc.remove_external_references(*targets)
52
22
  end
53
-
54
- svn :propdel, 'svn:externals', *args
55
- logging_stream.puts "Done converting existing svn:externals to Piston"
56
23
  end
57
24
 
58
- def skip_no_externals(dir)
59
- logging_stream.puts "Skipping '#{dir}' - no svn:externals definition"
60
- end
61
-
62
- def skip_no_match(external)
63
- logging_stream.puts "#{external.inspect} did not match Regexp"
64
- end
65
-
66
- def self.help
67
- "Converts existing svn:externals into Piston managed folders"
68
- end
69
-
70
- def self.detailed_help
71
- <<EOF
72
- usage: convert [DIR [...]]
73
-
74
- Converts folders which have the svn:externals property set to Piston managed
75
- folders.
76
- EOF
77
- end
78
- end
79
- end
25
+ def start(*args)
26
+ targets = args.flatten.map {|d| Pathname.new(d).expand_path}
27
+ run(targets)
28
+ puts "#{targets.length} directories converted"
29
+ end
30
+ end
31
+ end
80
32
  end
@@ -1,55 +1,23 @@
1
- require "piston"
2
- require "piston/command"
3
- require 'find'
1
+ require "piston/commands/base"
4
2
 
5
3
  module Piston
6
4
  module Commands
7
- class Diff < Piston::Command
5
+ class Diff < Piston::Commands::Base
8
6
  def run
9
- (args.empty? ? find_targets : args).each do |dir|
10
- diff dir
11
- end
7
+ working_copy = working_copy!(options[:wcdir])
8
+ working_copy.diff
12
9
  end
13
10
 
14
- def diff(dir)
15
- return unless File.directory?(dir)
16
- logging_stream.puts "Processing '#{dir}'..."
17
- repos = svn(:propget, Piston::ROOT, dir).chomp
18
- uuid = svn(:propget, Piston::UUID, dir).chomp
19
- remote_revision = svn(:propget, Piston::REMOTE_REV, dir).chomp.to_i
20
-
21
- logging_stream.puts " Fetching remote repository's latest revision and UUID"
22
- info = YAML::load(svn(:info, repos))
23
- return skip(dir, "Repository UUID changed\n Expected #{uuid}\n Found #{info['Repository UUID']}\n Repository: #{repos}") unless uuid == info['Repository UUID']
24
-
25
- logging_stream.puts " Checking out repository at revision #{remote_revision}"
26
- svn :checkout, '--ignore-externals', '--quiet', '--revision', remote_revision, repos, dir.tmp
27
-
28
- puts run_diff(dir.tmp, dir)
29
-
30
- logging_stream.puts " Removing temporary files / folders"
31
- FileUtils.rm_rf dir.tmp
32
-
33
- end
34
-
35
- def run_diff(dir1, dir2)
36
- `diff -urN --exclude=.svn #{dir1} #{dir2}`
37
- end
38
-
39
- def self.help
40
- "Shows the differences between the local repository and the pristine upstream"
41
- end
42
-
43
- def self.detailed_help
44
- <<EOF
45
- usage: diff [DIR [...]]
46
-
47
- This operation has the effect of producing a diff between the pristine upstream
48
- (at the last updated revision) and your local version. In other words, it
49
- gives you the changes you have made in your repository that have not been
50
- incorporated upstream.
51
- EOF
52
- end
11
+ def start(*args)
12
+ args.flatten.map {|d| Pathname.new(d).expand_path}.each do |wcdir|
13
+ begin
14
+ options[:wcdir] = wcdir
15
+ run
16
+ rescue Piston::WorkingCopy::NotWorkingCopy
17
+ puts "#{wcdir} is not a working copy"
18
+ end
19
+ end
20
+ end
53
21
  end
54
22
  end
55
23
  end