public
Rubygem
Description: Piston is a utility that eases vendor branch management. This repository is a complete reimplementation of Piston to provide different backends, depending on the repositories and working copies you pistonize from.
Homepage: http://piston.rubyforge.org/
Clone URL: git://github.com/francois/piston.git
francois (author)
Tue Jul 22 17:30:27 -0700 2008
commit  901fc54379d08b74db35b9fd7f83780b66d85f30
tree    c5836776f9ddd5330190d99f215c23f1fd58b2a2
parent  30cd1701b3252d80d70926bd01ef7d73b9b2910f
piston / lib / piston / svn / working_copy.rb
100644 101 lines (86 sloc) 3.085 kb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
require "yaml"
 
module Piston
  module Svn
    class WorkingCopy < Piston::WorkingCopy
      # Register ourselves as a handler for working copies
      Piston::WorkingCopy.add_handler self
 
      class << self
        def understands_dir?(dir)
          result = svn(:info, dir) rescue :failed
          result == :failed ? false : true
        end
 
        def client
          @@client ||= Piston::Svn::Client.instance
        end
 
        def svn(*args)
          client.svn(*args)
        end
      end
 
      def svn(*args)
        self.class.svn(*args)
      end
 
      def exist?
        result = svn(:info, path) rescue :failed
        logger.debug {"result: #{result.inspect}"}
        return false if result == :failed
        return false if result.nil? || result.chomp.strip.empty?
        return true if YAML.load(result).has_key?("Path")
      end
 
      def create
        svn(:mkdir, path)
      end
 
      def after_remember(path)
        info = svn(:info, path)
        return unless info =~ /\(not a versioned resource\)/i || info.empty?
        svn(:add, path)
      end
 
      def finalize
        targets = []
        Dir[path + "*"].each do |item|
          svn(:add, item)
        end
      end
 
      # Returns all defined externals (recursively) of this WC.
      # Returns a Hash:
      # {"vendor/rails" => {:revision => :head, :url => "http://dev.rubyonrails.org/svn/rails/trunk"},
      # "vendor/plugins/will_paginate" => {:revision => 1234, :url => "http://will_paginate.org/svn/trunk"}}
      def externals
        externals = svn(:proplist, "--recursive", "--verbose")
        return Hash.new if externals.blank?
        returning(Hash.new) do |result|
          YAML.load(externals).each_pair do |dir, props|
            next if props["svn:externals"].blank?
            next unless dir =~ /Properties on '([^']+)'/
            basedir = self.path + $1
            exts = props["svn:externals"]
            exts.split("\n").each do |external|
              data = external.match(/^([^\s]+)\s+(?:(?:-r|--revision)\s*(\d+)\s+)?(.+)$/)
              case data.length
              when 4
                subdir, rev, url = data[1], data[2].nil? ? :head : data[2].to_i, data[3]
              else
                raise SyntaxError, "Could not parse svn:externals on #{basedir}: #{external}"
              end
 
              result[basedir + subdir] = {:revision => rev, :url => url}
            end
          end
        end
      end
 
      def update(from, to, todir)
        logger.info "Copying new changes in place"
        copy_from(to)
        logger.info "Merging local changes into working copy"
        merge_changes(from, to, todir)
      end
 
      def merge_changes(from, to, todir)
        data = svn(:info, yaml_path)
        info = YAML.load(data)
        initial_revision = info["Last Changed Rev"].to_i.succ
        svn(:merge, "--revision", "#{initial_revision}:#{to.revision}", from.url, path)
      end
 
      def remove_external_references(*targets)
        svn(:propdel, "svn:externals", *targets)
      end
    end
  end
end