Class: Svn::Scm::Adapters::Subversion

Inherits:
Struct
  • Object
show all
Defined in:
lib/Svn/scm/adapters/subversion.rb

Defined Under Namespace

Classes: ScmCommandAborted

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeSubversion

Returns a new instance of Subversion.



9
10
11
12
13
14
15
16
# File 'lib/Svn/scm/adapters/subversion.rb', line 9

def initialize
	options = YAML.load(File.open("#{Rails.root}/config/configuration.yml")).values.first
	self.url = options['url']
	self. = options['login']
	self.password = options['password']
	self.root_url = options['root_url']
	self.root_name = url.gsub(Regexp.new(root_url),'')
end

Instance Attribute Details

#loginObject

Returns the value of attribute login

Returns:

  • (Object)

    the current value of login



6
7
8
# File 'lib/Svn/scm/adapters/subversion.rb', line 6

def 
  @login
end

#passwordObject

Returns the value of attribute password

Returns:

  • (Object)

    the current value of password



6
7
8
# File 'lib/Svn/scm/adapters/subversion.rb', line 6

def password
  @password
end

#root_nameObject

Returns the value of attribute root_name

Returns:

  • (Object)

    the current value of root_name



6
7
8
# File 'lib/Svn/scm/adapters/subversion.rb', line 6

def root_name
  @root_name
end

#root_urlObject

Returns the value of attribute root_url

Returns:

  • (Object)

    the current value of root_url



6
7
8
# File 'lib/Svn/scm/adapters/subversion.rb', line 6

def root_url
  @root_url
end

#urlObject

Returns the value of attribute url

Returns:

  • (Object)

    the current value of url



6
7
8
# File 'lib/Svn/scm/adapters/subversion.rb', line 6

def url
  @url
end

Class Method Details

.load_entries_changesets(entries) ⇒ Object



167
168
169
170
171
172
173
174
175
# File 'lib/Svn/scm/adapters/subversion.rb', line 167

def self.load_entries_changesets(entries)
	return unless entries.present?
	entries_with_identifier = entries.select {|entry| entry.lastrev && entry.lastrev.identifier.present?}
	identifiers = entries_with_identifier.map {|entry| entry.lastrev.identifier}.compact.uniq
	if identifiers.any?
		change_ident = SvnRecord::Repository::Change.where(revision: identifiers).dup.group_by(&:revision)
		entries_with_identifier.each {|entry| entry.changeset = change_indent[entry.lastrev.identifier] if change_indent[entry.lastrev.identifier] }
	end
end

Instance Method Details

#cat(path, identifier = nil, cat = nil) ⇒ Object



127
128
129
130
131
132
133
134
# File 'lib/Svn/scm/adapters/subversion.rb', line 127

def cat(path, identifier=nil, cat=nil)
	identifier = (identifier and identifier.to_i > 0) ? identifier.to_i : "HEAD"
	path = path.gsub(Regexp.new("#{root_name}/"),'')
	cmd = "svn cat #{target(path)}@#{identifier} #{credentials_string}"
	shellout(cmd, {mark: true}) {|io|  io.binmode;  cat = io.read }
	return nil if $? && $?.exitstatus != 0
	cat
end

#diff(path, identifier_from, identifier_to = nil) ⇒ Object



111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# File 'lib/Svn/scm/adapters/subversion.rb', line 111

def diff(path, identifier_from, identifier_to=nil)
	path ||= ''
	identifier_from = (identifier_from and identifier_from.to_i > 0) ? identifier_from.to_i : ''
	identifier_to = (identifier_to and identifier_to.to_i > 0) ? identifier_to.to_i : (identifier_from.to_i - 1)
	cmd = "svn diff -r "
	cmd << "#{identifier_to}:"
	cmd << "#{identifier_from}"
	cmd << " #{target(path)}@#{identifier_from} #{credentials_string}" 
	diff = []
	shellout(cmd, {mark: true}) {|io|  io.each_line { |line| diff << line } }
	return nil if $? && $?.exitstatus != 0
	diff
rescue
	nil
end

#entries(path = '', identifier = nil, options = {}) ⇒ Object



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
# File 'lib/Svn/scm/adapters/subversion.rb', line 44

def entries(path='', identifier=nil, options={})
	identifier = identifier.to_i > 0 ? identifier.to_i : "HEAD"
	entries = Entries.new
	cmd = " svn list --xml #{target(path)}@#{identifier}  #{credentials_string}" 
	shellout(cmd) do |doc,_|
		begin 
			changes = SvnRecord::Repository::Change.all.dup
			each_xml_element(doc['lists']['list'], 'entry') do |entry|
				commit = entry['commit']
				commit_date = commit['date']
				next if entry['kind'] == 'dir' && commit_date.nil?
				name = entry['name']['__content__']
				entries << Entry.new({:name => URI.unescape(name),
					:path => ((path.empty? ? "" : "#{path}/") + name),
					:kind => entry['kind'],
					:size => ((s = entry['size']) ? s['__content__'].to_i : nil),
					:lastrev => Revision.new({
						:identifier => commit['revision'],
						:time => Time.parse(commit_date['__content__'].to_s).localtime,
						:author => ((a = commit['author']) ? a['__content__'] : nil),
						:message => (change = changes.detect{|a| a.revision == commit['revision'].to_i}) ? change.comment : ""
						})
						})
					end
		rescue Exception => e
			Rails.logger.error("Error parsing svn output: #{e.message}")
		end
	end
	return nil if $? && $?.exitstatus != 0
	entries.sort_by_name
end

#fetch_changesetsObject



142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
# File 'lib/Svn/scm/adapters/subversion.rb', line 142

def fetch_changesets
	if (scm_info = self.class.new.info)
		change = SvnRecord::Repository::Change.last
		db_revision =  change.present?  ?  change.revision.to_i : 0
		scm_revision = scm_info.lastrev.identifier.to_i
		branch = scm_info.lastrev.branch.present? ?  scm_info.lastrev.branch : "master"
		if db_revision < scm_revision
			#	debug("Fetching changesets for repository #{url}" )
			identifier_from = db_revision + 1
			while (identifier_from <= scm_revision)
				identifier_to = [identifier_from + 199, scm_revision].min
				revisions('', identifier_to, identifier_from, :with_paths => true).reverse_each do |revision|
					ActiveRecord::Base.transaction do
						user = SvnRecord::Repository::User.find_by_name(revision.author.to_s.strip)
						user = SvnRecord::Repository::User.create(name: revision.author.to_s.strip) if user.blank? && revision.author.to_s.strip.present?
						changeset = SvnRecord::Repository::Change.create(user_id: user.id, revision:revision.identifier, committer:revision.author, committed_at: revision.time, comment: revision.message)
						revision.paths.each { |change| changeset.create_change(change,branch)} unless changeset.new_record?
					end
				end if revisions.present?
				identifier_from = identifier_to + 1
			end
		end
	end
end

#infoObject



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

def info
	info = nil
	cmd = "svn info --xml #{target}"
	cmd << credentials_string
	shellout(cmd){ |doc,_| info = Info.get_instance(doc) }
	info
end

#latest_changesets(path, rev, limit = 10) ⇒ Object



137
138
139
140
# File 'lib/Svn/scm/adapters/subversion.rb', line 137

def latest_changesets(path, rev, limit=10)
	revisions = self.class.scm.revisions(path, rev, nil, :limit => limit).map(&:identifier).compact
	evisions.present? ? SvnRecord::Repository::Change.where(revision: revisions).order('revision DESC').all : []
end

#revisions(path = '', identifier_from = nil, identifier_to = nil, options = {}) ⇒ Object



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
102
103
104
105
106
107
108
109
# File 'lib/Svn/scm/adapters/subversion.rb', line 76

def revisions(path='', identifier_from=nil, identifier_to=nil, options={})
identifier_from = (identifier_from && identifier_from.to_i > 0) ? identifier_from.to_i : "HEAD"
identifier_to = (identifier_to && identifier_to.to_i > 0) ? identifier_to.to_i : 1
revisions = Revisions.new
cmd = "svn log --xml -r #{identifier_from}:#{identifier_to}"
cmd << credentials_string
cmd << " --verbose " if  options[:with_paths]
cmd << " --limit #{options[:limit].to_i}" if options[:limit]
cmd << ' ' + target(path)
shellout(cmd) do |doc,_|
	begin 
		each_xml_element(doc['log'], 'logentry') do |logentry|
			paths = []
			each_xml_element(logentry['paths'], 'path') do |path|
				paths << { :action => path['action'],
					:path => path['__content__'],
					:from_path => path['copyfrom-path'],
					:from_revision => path['copyfrom-rev']
				}
			end if logentry['paths'] && logentry['paths']['path']
			paths.sort! { |x,y| x[:path] <=> y[:path] }
			revisions << Revision.new({:identifier => logentry['revision'],
				:author => (logentry['author'] ? logentry['author']['__content__'] : ""),
				:time => Time.parse(logentry['date']['__content__'].to_s).localtime,
				:message => logentry['msg']['__content__'],
				:paths => paths
				})
			end
		rescue
		end
	end
	return nil if $? && $?.exitstatus != 0
	revisions
end

#shellout(cmd, options = {}, &block) ⇒ Object

shellout



19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# File 'lib/Svn/scm/adapters/subversion.rb', line 19

def shellout(cmd, options = {}, &block)
	Rails.logger.debug("Shelling out: #{strip_credential(cmd)}" )
	IO.popen(cmd, "r+") do |io|
		io.set_encoding("ASCII-8BIT") if io.respond_to?(:set_encoding)
		io.close_write unless options[:write_stdin]
		if options[:mark]
			block.call(io) if block_given?
		else
			output = io.read
			output.force_encoding('UTF-8') if output.respond_to?(:force_encoding)
			doc = parse_xml(output)
			block.call(doc,output) if block_given?
		end
	end
rescue
end