realityforge-piston 1.4.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,81 @@
1
+ 1.4.1 (Pending)
2
+
3
+ 1.4.0 (2008-02-07)
4
+ * New piston diff subcommand, implemented by Graeme Mathieson.
5
+ http://rubyforge.org/tracker/index.php?func=detail&aid=17116&group_id=2105&atid=8179
6
+ * Per http://rubyforge.org/tracker/?func=detail&atid=8179&aid=10717&group_id=2105
7
+ Don't set LC_ALL, but set LANGUAGE so that repositories with foreign
8
+ characters can be used. Thanks go to Per Wigren.
9
+
10
+ 1.3.3 (2007-03-22)
11
+ * Repaired problems with import subcommand. Wrote specifications to prevent
12
+ the same failure mode again.
13
+
14
+ 1.3.2 (2007-03-09)
15
+ * piston switch had a bad constant access which caused failures.
16
+
17
+ 1.3.1 (2007-03-09)
18
+ * piston switch would fail if the branch from which we are reading had been
19
+ deleted.
20
+ * piston switch had a major bug. It did not update the piston:root property
21
+ to remember the new repository root. Reported and fixed by Graeme
22
+ Mathieson.
23
+ * piston switch errors out early if not provided with the right arguments.
24
+ Thanks to Graeme Mathieson for the info and patch.
25
+ * New internal command parser. No visible external changes.
26
+
27
+ 1.3.0 (2007-01-22)
28
+ * Piston status shows the revision number of locked repositories. Thanks to
29
+ Chris Wanstrath <http://errtheblog.com/>.
30
+ * New piston switch subcommand to switch repository locations. Thanks to
31
+ Greg Spurrier for the prompt which resulted in finally implementing this.
32
+
33
+ 1.2.1 (2006-11-20)
34
+ * Import subcommand would fail with a "svn: Explicit target required
35
+ ('vendor/rails' interpreted as prop value)" error. This was a minor
36
+ error in the import code. Reported by Daniel N.
37
+ * The import subcommand could import another revision than what was intended,
38
+ if HEAD was updated while the import is in progress.
39
+
40
+ 1.2.0 (2006-11-17)
41
+ * New status subcommand. Shows M if locally or remotely modified. Applies to
42
+ one, many, all folders. This subcommand *requires* the use of a Subversion
43
+ 1.2.0 client. Thanks to Chris Wanstrath for the inspiration. His Rake
44
+ tasks are available at http://errtheblog.com/post/38.
45
+ * Minor patch by Miguel Ibero Carreras to make Subversion always use the
46
+ C locale, instead of the current one. This allows Piston to be used
47
+ with internationalized versions of Subversion. David Bittencourt later
48
+ reported the same problem. Thanks!
49
+ * Better handle how update finds it's latest local revision to prevent
50
+ conflicts. If you had never locally changed your vendor repositories,
51
+ this fix will change nothing for you. This helps prevent local conflicts
52
+ if you had ever applied a local patch.
53
+ *CAVEAT*: See the release announcement at
54
+ http://blog.teksol.info/articles/2006/11/17/piston-1-2-0-status-better-update
55
+ for a required local operation.
56
+
57
+ 1.1.1 (2006-08-30)
58
+ * Add contrib/piston [Michael Schuerig]
59
+ * Non-recursively add the root directory of the managed folder then set Piston
60
+ properties before adding the contents of the managed folder. This is to
61
+ help ease work along if an inconsistent EOL is encountered during the
62
+ import. The user can finish the import by svn add'ing the rest of the
63
+ folder until all files are added. Piston properties will already have been
64
+ set.
65
+
66
+ 1.1.0 (2006-08-26)
67
+ * New 'convert' subcommand converts existing svn:externals to Piston managed
68
+ folders. Thanks to Dan Kubb for the idea.
69
+ * update now recursively finds the folders to process. It bases it's search
70
+ on the presence or absence of the piston:root property.
71
+ * Changed lock and unlock messages to be more detailed.
72
+
73
+ 1.0.1 (2006-08-24)
74
+ * Corrected minor bug where the core extensions were in core_ext/core_ext
75
+ instead of being in core_ext.
76
+ * Require the parent working copy path be at HEAD before importing / updating.
77
+ * Don't do unnecessary merges if the file had not changed prior to the update.
78
+ * During the update, if adding a folder, do an svn mkdir instead of a cp_r.
79
+
80
+ 1.0.0 (2006-08-24)
81
+ * Initial version
data/LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2006 Francois Beausoleil <francois@teksol.info>
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
@@ -0,0 +1,134 @@
1
+ Piston is a utility that eases vendor branch management.
2
+ This is similar to <tt>svn:externals</tt>, except you have a local copy of
3
+ the files, which you can modify at will. As long as the changes are
4
+ mergeable, you should have no problems.
5
+
6
+ This tool has a similar purpose than svnmerge.py which you can find in the
7
+ contrib/client-side folder of the main Subversion repository at
8
+ http://svn.collab.net/repos/svn/trunk/contrib/client-side/svnmerge.py.
9
+ The main difference is that Piston is designed to work with remote
10
+ repositories. Another tool you might want to look at, SVK, which you can find
11
+ at http://svk.elixus.org/.
12
+
13
+ From Wikipedia's Piston page (http://en.wikipedia.org/wiki/Piston):
14
+ In general, a piston is a sliding plug that fits closely inside the bore
15
+ of a cylinder.
16
+
17
+ Its purpose is either to change the volume enclosed by the cylinder, or
18
+ to exert a force on a fluid inside the cylinder.
19
+
20
+ For this utility, I retain the second meaning, "to exert a force on a fluid
21
+ inside the cylinder." Piston forces the content of a remote repository
22
+ location back into our own.
23
+
24
+
25
+ = Installation
26
+
27
+ Nothing could be simpler:
28
+
29
+ $ gem install --include-dependencies piston
30
+
31
+
32
+ = Usage
33
+
34
+ First, you need to import the remote repository location:
35
+
36
+ $ piston import http://dev.rubyonrails.org/svn/rails/trunk vendor/rails
37
+ Exported r4720 from 'http://dev.rubyonrails.org/svn/rails/trunk' to 'vendor/rails'
38
+
39
+ $ svn commit -m "Importing local copy of Rails"
40
+
41
+ When you want to get the latest changes from the remote repository location:
42
+
43
+ $ piston update vendor/rails
44
+ Updated 'vendor/rails' to r4720.
45
+
46
+ $ svn commit -m "Updates vendor/rails to the latest revision"
47
+
48
+ You can prevent a local Piston-managed folder from updating by using the
49
+ +lock+ subcommand:
50
+
51
+ $ piston lock vendor/rails
52
+ 'vendor/rails' locked at r4720.
53
+
54
+ When you want to update again, you unlock:
55
+
56
+ $ piston unlock vendor/rails
57
+ 'vendor/rails' unlocked.
58
+
59
+ If the branch you are following moves, you should use the switch subcommand:
60
+
61
+ $ piston import http://dev.rubyonrails.org/svn/rails/branches/1-2-pre-release vendor/rails
62
+ $ svn commit vendor/rails
63
+
64
+ # Vendor branch is renamed, let's follow it
65
+ $ piston switch http://dev.rubyonrails.org/svn/rails/branches/1-2-stable vendor/rails
66
+
67
+
68
+ = Contributions
69
+
70
+ == Bash Shell Completion Script
71
+
72
+ Michael Schuerig contributed a Bash shell completion script. You should copy
73
+ +contrib/piston+ from your gem repository to the appropriate folder. Michael
74
+ said:
75
+
76
+ I've put together a bash completion function for piston. On Debian, I
77
+ just put it in /etc/bash_completion.d, alternatively, the contents can
78
+ be copied to ~/.bash_completion. I don't know how things are organized
79
+ on other Unix/Linux systems.
80
+
81
+
82
+ = Caveats
83
+
84
+ == Speed
85
+
86
+ This tool is SLOW. The update process particularly so. I use a brute force
87
+ approach. Subversion cannot merge from remote repositories, so instead I
88
+ checkout the folder at the initial revision, and then run svn update and
89
+ parse the results of that to determine what changes have occured.
90
+
91
+ If a local copy of a file was changed, it's changes will be merged back in.
92
+ If that introduces a conflict, Piston will not detect it. The commit will be
93
+ rejected by Subversion anyway.
94
+
95
+ == Copies / Renames
96
+
97
+ Piston *does not* track copies. Since Subversion does renames in two
98
+ phases (copy + delete), that is what Piston does.
99
+
100
+ == Local Operations Only
101
+
102
+ Piston only works if you have a working copy. It also never commits your
103
+ working copy directly. You are responsible for reviewing the changes and
104
+ applying any pending fixes.
105
+
106
+ == Remote Repository UUID
107
+
108
+ Piston caches the remote repository UUID, allowing it to know if the remote
109
+ repos is still the same. Piston refuses to work against a different
110
+ repository than the one we checked out from originally.
111
+
112
+
113
+ = Subversion Properties Used
114
+
115
+ * <tt>piston:uuid</tt>: The remote repository's UUID, which we always confirm
116
+ before doing any operations.
117
+ * <tt>piston:root</tt>: The repository root URL from which this Piston folder
118
+ was exported from.
119
+ * <tt>piston:remote-revision</tt>: The <tt>Last Changed Rev</tt> of the remote
120
+ repository.
121
+ * <tt>piston:local-revision</tt>: The <tt>Last Changed Rev</tt> of the Piston
122
+ managed folder, to enable us to know if we need to do any merging.
123
+ * <tt>piston:locked</tt>: The revision at which this folder is locked. If
124
+ this property is set and non-blank, Piston will skip the folder with
125
+ an appropriate message.
126
+
127
+
128
+ = Dependencies
129
+
130
+ Piston depends on the following libraries:
131
+
132
+ * yaml
133
+ * uri
134
+ * fileutils
@@ -0,0 +1,25 @@
1
+ require 'rake'
2
+ require 'rake/rdoctask'
3
+ require 'rake/gempackagetask'
4
+ require 'spec/rake/spectask'
5
+ require File.join(File.dirname(__FILE__), 'lib', 'piston', 'version')
6
+
7
+ gem_spec = Gem::Specification.load(File.expand_path('piston.gemspec', File.dirname(__FILE__)))
8
+
9
+ Spec::Rake::SpecTask.new(:spec) do |spec|
10
+ spec.libs << 'lib' << 'spec'
11
+ spec.spec_files = FileList['specs/**/*_spec.rb']
12
+ end
13
+
14
+ task :default => :spec
15
+
16
+ desc "Generate RDoc documentation in rdoc/"
17
+ Rake::RDocTask.new :rdoc do |rdoc|
18
+ rdoc.rdoc_dir = 'rdoc'
19
+ rdoc.title = gem_spec.name
20
+ rdoc.options = gem_spec.rdoc_options.clone
21
+ rdoc.rdoc_files.include('lib/**/*.rb')
22
+ rdoc.rdoc_files.include gem_spec.extra_rdoc_files
23
+ end
24
+
25
+ Rake::GemPackageTask.new(gem_spec).define
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+
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
@@ -0,0 +1,43 @@
1
+ have piston &&
2
+ _piston()
3
+ {
4
+ local cur prev commands options command
5
+
6
+ COMPREPLY=()
7
+ cur=${COMP_WORDS[COMP_CWORD]}
8
+
9
+ commands='update convert help unlock lock import switch'
10
+
11
+ if [[ $COMP_CWORD -eq 1 ]] ; then
12
+ if [[ "$cur" == -* ]]; then
13
+ COMPREPLY=( $( compgen -W '--version' -- $cur ) )
14
+ else
15
+ COMPREPLY=( $( compgen -W "$commands" -- $cur ) )
16
+ fi
17
+ else
18
+
19
+ prev=${COMP_WORDS[COMP_CWORD-1]}
20
+ command=${COMP_WORDS[1]}
21
+
22
+ if [[ "$cur" == -* ]]; then
23
+ case $command in
24
+ @(update|import))
25
+ options='-r --revision --lock --verbose'
26
+ ;;
27
+ esac
28
+ options="$options --verbose"
29
+
30
+ COMPREPLY=( $( compgen -W "$options" -- $cur ) )
31
+ else
32
+ if [[ "$command" == @(help|h|\?) ]]; then
33
+ COMPREPLY=( $( compgen -W "$commands" -- $cur ) )
34
+ else
35
+ _filedir
36
+ fi
37
+ fi
38
+ fi
39
+
40
+ return 0
41
+ }
42
+
43
+ [ -n "${have:-}" ] && complete -F _piston $default piston
@@ -0,0 +1,5 @@
1
+ class Range
2
+ def to_svn
3
+ to_s.gsub(/\.{2,3}/, ':')
4
+ end
5
+ end
@@ -0,0 +1,9 @@
1
+ class String
2
+ def tmp
3
+ self + ".tmp"
4
+ end
5
+
6
+ def blank?
7
+ self.empty? || self.strip.empty?
8
+ end
9
+ end
@@ -0,0 +1,70 @@
1
+ # Copyright (c) 2006 Francois Beausoleil <francois@teksol.info>
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in
11
+ # all copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ # THE SOFTWARE.
20
+
21
+ # $HeadURL: svn+ssh://rubyforge.org/var/svn/piston/tags/1.4.0/lib/piston.rb $
22
+ # $Id: piston.rb 139 2008-02-07 15:28:24Z fbos $
23
+
24
+ require 'yaml'
25
+ require 'uri'
26
+ require 'fileutils'
27
+
28
+ PISTON_ROOT = File.dirname(__FILE__)
29
+ Dir[File.join(PISTON_ROOT, 'core_ext', '*.rb')].each do |file|
30
+ require file
31
+ end
32
+
33
+ require "piston/version"
34
+ require "piston/command"
35
+ require "piston/command_error"
36
+
37
+ require "transat/parser"
38
+ Dir[File.join(PISTON_ROOT, "piston", "commands", "*.rb")].each do |file|
39
+ require file.gsub(PISTON_ROOT, "")[1..-4]
40
+ end
41
+
42
+ module Piston
43
+ ROOT = "piston:root"
44
+ UUID = "piston:uuid"
45
+ REMOTE_REV = "piston:remote-revision"
46
+ LOCAL_REV = "piston:local-revision"
47
+ LOCKED = "piston:locked"
48
+ end
49
+
50
+ PistonCommandLineProcessor = Transat::Parser.new do
51
+ program_name "Piston"
52
+ version [Piston::VERSION::STRING]
53
+
54
+ option :verbose, :short => :v, :default => true, :message => "Show subversion commands and results as they are executed"
55
+ option :quiet, :short => :q, :default => false, :message => "Do not output any messages except errors"
56
+ option :revision, :short => :r, :param_name => "REVISION", :type => :int
57
+ option :show_updates, :short => :u, :message => "Query the remote repository for out of dateness information"
58
+ option :lock, :short => :l, :message => "Close down and lock the imported directory from further changes"
59
+ option :dry_run, :message => "Does not actually execute any commands"
60
+ option :force, :message => "Force the command to run, even if Piston thinks it would cause a problem"
61
+
62
+ command :switch, Piston::Commands::Switch, :valid_options => %w(lock dry_run force revision quiet verbose)
63
+ command :update, Piston::Commands::Update, :valid_options => %w(lock dry_run force revision quiet verbose)
64
+ command :diff, Piston::Commands::Diff, :valid_options => %w(lock dry_run force revision quiet verbose)
65
+ command :import, Piston::Commands::Import, :valid_options => %w(lock dry_run force revision quiet verbose)
66
+ command :convert, Piston::Commands::Convert, :valid_options => %w(lock verbose dry_run)
67
+ command :unlock, Piston::Commands::Unlock, :valid_options => %w(force dry_run verbose)
68
+ command :lock, Piston::Commands::Lock, :valid_options => %w(force dry_run revision verbose)
69
+ command :status, Piston::Commands::Status, :valid_options => %w(show_updates verbose)
70
+ end
@@ -0,0 +1,68 @@
1
+ require "piston"
2
+
3
+ module Piston
4
+ # The base class which all commands subclass to obtain services from.
5
+ class Command
6
+ attr_accessor :revision, :dry_run, :quiet, :verbose, :force, :lock,
7
+ :recursive, :show_updates
8
+ attr_reader :args
9
+ attr_writer :logging_stream
10
+
11
+ def initialize(non_options, options)
12
+ @args = non_options
13
+
14
+ # Because the Windows shell does not process wildcards, we must do it
15
+ # here ourselves
16
+ @args.collect! do |arg|
17
+ next arg unless arg =~ /[*?]/
18
+ Dir[arg]
19
+ end
20
+
21
+ options.each do |option, value|
22
+ self.send("#{option}=", value)
23
+ end
24
+ end
25
+
26
+ # Run a Subversion command using the shell. If the Subversion command
27
+ # returns an existstatus different from zero, a RuntimeError is raised.
28
+ def svn(*args)
29
+ args = args.flatten.compact.map do |arg|
30
+ if arg.to_s =~ /[ *?@]/ then
31
+ %Q("#{arg}")
32
+ else
33
+ arg
34
+ end
35
+ end
36
+
37
+ command = "svn #{args.join(' ')}"
38
+ logging_stream.puts command if verbose
39
+ return if dry_run
40
+ ENV['LANGUAGE'] = 'en_US'
41
+ result = `#{command}`
42
+ logging_stream.puts result if verbose
43
+ raise "Command #{command} resulted in an error:\n\n#{result}" unless $?.exitstatus.zero?
44
+ result
45
+ end
46
+
47
+ # Returns an IO-like object to which all information should be logged.
48
+ def logging_stream
49
+ @logging_stream ||= $stdout
50
+ end
51
+
52
+ def skip(dir, msg, header=true)
53
+ logging_stream.print "Skipping '#{dir}': " if header
54
+ logging_stream.puts msg
55
+ end
56
+
57
+ def find_targets
58
+ targets = Array.new
59
+ svn(:propget, '--recursive', Piston::ROOT).each_line do |line|
60
+ next unless line =~ /^([^ ]+)\s-\s.*$/
61
+ targets << $1
62
+ end
63
+
64
+ targets
65
+ end
66
+
67
+ end
68
+ end