Class: RSCM::Subversion

Inherits:
Base
  • Object
show all
Includes:
FileUtils, PathConverter
Defined in:
lib/rscm/scm/subversion.rb

Overview

RSCM implementation for Subversion.

You need the svn/svnadmin executable on the PATH in order for it to work.

NOTE: On Cygwin these have to be the win32 builds of svn/svnadmin and not the Cygwin ones.

Constant Summary

Constants included from RevisionPoller

RevisionPoller::BASE_INCREMENT, RevisionPoller::CRITICAL_REVISION_SIZE, RevisionPoller::TWENTY_FOUR_HOURS

Instance Attribute Summary collapse

Attributes inherited from Base

#default_options, #store_revisions_command

Attributes included from RevisionPoller

#logger

Instance Method Summary collapse

Methods included from PathConverter

ensure_trailing_slash, filepath_to_nativepath, filepath_to_nativeurl, nativepath_to_filepath

Methods inherited from Base

#==, #available?, #checked_out_files, #checkout, #checkout_commandline, #checkout_dir, #checkout_dir=, #destroy_working_copy, #edit, #store_revisions_command?, #to_yaml_properties, #update_commandline

Methods included from RevisionPoller

#poll

Constructor Details

#initialize(url = "", path = "") ⇒ Subversion

Returns a new instance of Subversion.


26
27
28
29
30
# File 'lib/rscm/scm/subversion.rb', line 26

def initialize(url="", path="")
  @url, @path = url, path
  @username = ""
  @password = ""
end

Instance Attribute Details

#passwordObject

Returns the value of attribute password


24
25
26
# File 'lib/rscm/scm/subversion.rb', line 24

def password
  @password
end

#pathObject

Must be specified in order to create repo and install triggers. Must also be specified as “” if the url represents the root of the repository, or files in revisions will not be detected.


22
23
24
# File 'lib/rscm/scm/subversion.rb', line 22

def path
  @path
end

#urlObject

Returns the value of attribute url


19
20
21
# File 'lib/rscm/scm/subversion.rb', line 19

def url
  @url
end

#usernameObject

Returns the value of attribute username


23
24
25
# File 'lib/rscm/scm/subversion.rb', line 23

def username
  @username
end

Instance Method Details

#add(relative_filename, options = {}) ⇒ Object


49
50
51
# File 'lib/rscm/scm/subversion.rb', line 49

def add(relative_filename, options={})
  svn("add #{checkout_dir}/#{relative_filename}", options)
end

#can_create_central?Boolean

Returns:

  • (Boolean)

95
96
97
# File 'lib/rscm/scm/subversion.rb', line 95

def can_create_central?
  local? && !path.nil? && !(path == "")
end

#central_exists?Boolean

Returns:

  • (Boolean)

107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# File 'lib/rscm/scm/subversion.rb', line 107

def central_exists?
  if(local?)
    File.exists?("#{svnrootdir}/db")
  else
    # Do a simple command over the network
    # If the repo/path doesn't exist, we'll get zero output
    # on stdout (and an error msg on std err).
    exists = false
    cmd = "svn log #{url} -r HEAD"
    execute(cmd) do |stdout|
      stdout.each_line do |line|
        exists = true
      end
    end
    exists
  end
end

#checked_out?Boolean

Returns:

  • (Boolean)

203
204
205
206
207
# File 'lib/rscm/scm/subversion.rb', line 203

def checked_out?
  rootentries = File.expand_path("#{checkout_dir}/.svn/entries")
  result = File.exists?(rootentries)
  result
end

#commit(message, options = {}) ⇒ Object


70
71
72
73
74
# File 'lib/rscm/scm/subversion.rb', line 70

def commit(message, options={})
  svn(commit_command(message), options)
  # We have to do an update to get the local revision right
  checkout_silent(nil, options)
end

#create_central(options = {}) ⇒ Object


136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# File 'lib/rscm/scm/subversion.rb', line 136

def create_central(options={})
  options = options.dup.merge({:dir => svnrootdir})
  native_path = PathConverter.filepath_to_nativepath(svnrootdir, false)
  mkdir_p(PathConverter.nativepath_to_filepath(native_path))
  svnadmin("create #{native_path}", options)
  if(path != "")
    options = options.dup.merge({:dir => "."})
    # create the directories
    paths = path.split("/")
    paths.each_with_index do |p,i|
      p = paths[0..i]
      u = "#{repourl}/#{p.join('/')}"
      svn("mkdir #{u} -m \"Adding directories\"", options)
    end
  end
end

#destroy_centralObject


99
100
101
102
103
104
105
# File 'lib/rscm/scm/subversion.rb', line 99

def destroy_central
  if(File.exist?(svnrootdir) && local?)
    FileUtils.rm_rf(svnrootdir)
  else
    raise "Cannot destroy central repository. '#{svnrootdir}' doesn't exist or central repo isn't local to this machine"
  end
end

#diff(path, from, to, options = {}, &block) ⇒ Object


80
81
82
83
84
85
# File 'lib/rscm/scm/subversion.rb', line 80

def diff(path, from, to, options={}, &block)
  cmd = "svn diff --revision #{from}:#{to} \"#{url}/#{path}\""
  execute(cmd, options) do |io|
    return(block.call(io))
  end
end

#import_central(dir, options = {}) ⇒ Object


171
172
173
174
# File 'lib/rscm/scm/subversion.rb', line 171

def import_central(dir, options={})
  import_cmd = "import #{dir} #{url} -m \"#{options[:message]}\""
  svn(import_cmd, options)
end

#install_trigger(trigger_command, trigger_files_checkout_dir, options = {}) ⇒ Object


153
154
155
156
157
158
159
# File 'lib/rscm/scm/subversion.rb', line 153

def install_trigger(trigger_command, trigger_files_checkout_dir, options={})
  if (WINDOWS)
    install_win_trigger(trigger_command, trigger_files_checkout_dir, options)
  else
    install_unix_trigger(trigger_command, trigger_files_checkout_dir, options)
  end
end

#installed?Boolean

Returns:

  • (Boolean)

36
37
38
39
40
41
42
43
# File 'lib/rscm/scm/subversion.rb', line 36

def installed?
  begin
    svn("--version", {}) 
    true
  rescue
    false
  end
end

#labelObject


76
77
78
# File 'lib/rscm/scm/subversion.rb', line 76

def label
  local_revision_identifier.to_s
end

#move(relative_src, relative_dest, options = {}) ⇒ Object


53
54
55
# File 'lib/rscm/scm/subversion.rb', line 53

def move(relative_src, relative_dest, options={})
  svn("mv #{checkout_dir}/#{relative_src} #{checkout_dir}/#{relative_dest}", options)
end

#open(path, native_revision_identifier, options = {}, &block) ⇒ Object


87
88
89
90
91
92
93
# File 'lib/rscm/scm/subversion.rb', line 87

def open(path, native_revision_identifier, options={}, &block)
  raise "native_revision_identifier cannot be nil" if native_revision_identifier.nil?
  cmd = "svn cat #{url}/#{path}@#{native_revision_identifier}"
  execute(cmd, options) do |io|
    return(block.call(io))
  end
end

#repourlObject

url pointing to the root of the repo


198
199
200
201
# File 'lib/rscm/scm/subversion.rb', line 198

def repourl
  last = (path.nil? || path == "") ? -1 : -(path.length)-2
  url[0..last]
end

#revisions(from_identifier = Time.new.utc, options = {}) ⇒ Object


176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
# File 'lib/rscm/scm/subversion.rb', line 176

def revisions(from_identifier=Time.new.utc, options={})
  raise "from_identifer cannot be nil" if from_identifier.nil?
  options = {
    :from_identifier => from_identifier,
    :to_identifier => Time.infinity, 
    :relative_path => "",
    :dir => Dir.pwd
  }.merge(options)
  
  checkout_dir = PathConverter.filepath_to_nativepath(@checkout_dir, false)
  revisions = nil
  command = "svn #{changes_command(options[:from_identifier], options[:to_identifier], options[:relative_path])}"
  execute(command, options) do |stdout|
    stdout = StringIO.new(stdout.read)
    parser = SubversionLogParser.new(stdout, @url, options[:from_identifier], options[:to_identifier], path)
    revisions = parser.parse_revisions
  end
  revisions.cmd = command if store_revisions_command?
  revisions
end

#supports_trigger?Boolean

Returns:

  • (Boolean)

125
126
127
128
129
130
# File 'lib/rscm/scm/subversion.rb', line 125

def supports_trigger?
  true
  # we'll assume it supports trigger even if not local. this is to ensure user interfaces
  # can display appropriate options, even if the object is not 'fully initialised'
  # local?
end

#to_identifier(raw_identifier) ⇒ Object


45
46
47
# File 'lib/rscm/scm/subversion.rb', line 45

def to_identifier(raw_identifier)
  raw_identifier.to_i
end

#transactional?Boolean

Returns:

  • (Boolean)

57
58
59
# File 'lib/rscm/scm/subversion.rb', line 57

def transactional?
  true
end

#trigger_installed?(trigger_command, trigger_files_checkout_dir, options = {}) ⇒ Boolean

Returns:

  • (Boolean)

165
166
167
168
169
# File 'lib/rscm/scm/subversion.rb', line 165

def trigger_installed?(trigger_command, trigger_files_checkout_dir, options={})
  return false unless File.exist?(post_commit_file)
  not_already_commented = LineEditor.comment_out(File.new(post_commit_file), /#{Regexp.escape(trigger_command)}/, "# ", "")
  not_already_commented
end

#trigger_mechanismObject


132
133
134
# File 'lib/rscm/scm/subversion.rb', line 132

def trigger_mechanism
  "hooks/post-commit"
end

#uninstall_trigger(trigger_command, trigger_files_checkout_dir, options = {}) ⇒ Object


161
162
163
# File 'lib/rscm/scm/subversion.rb', line 161

def uninstall_trigger(trigger_command, trigger_files_checkout_dir, options={})
  File.comment_out(post_commit_file, /#{Regexp.escape(trigger_command)}/, nil)
end

#uptodate?(identifier, options = {}) ⇒ Boolean

Returns:

  • (Boolean)

61
62
63
64
65
66
67
68
# File 'lib/rscm/scm/subversion.rb', line 61

def uptodate?(identifier, options={})
  if(!checked_out?)
    false
  else
    rev = identifier.nil? ? head_revision_identifier(options) : identifier 
    local_revision_identifier(options) == rev
  end
end