motomike-bnr_tools 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,4 @@
1
+ ---
2
+ :minor: 0
3
+ :patch: 2
4
+ :major: 0
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env ruby
2
+ begin
3
+ require 'rubygems'
4
+ gem 'bnr_tools'
5
+ rescue LoadError
6
+ $: << File.expand_path(File.dirname(__FILE__)) + "/../lib"
7
+ require 'bnr_tools'
8
+ end
9
+
10
+ require 'mergeinator'
11
+ require 'ticket'
12
+ require 'trollop'
13
+
14
+ CURRENT_RELEASE_BRANCH="9.4"
15
+
16
+ opts = Trollop::options do
17
+ opt :ticket, "A ticket number optionally followed by one or more changesets to merge", :type => :ints, :multi => true
18
+ opt :wc_root_path, "Root path to a working copy of the repository we can do merge gymnastics in", :default => "#{ENV["HOME"]}/diggRepository"
19
+ opt :release_branch, "Name of the release branch which will be the merge target", :default => CURRENT_RELEASE_BRANCH, :required => true, :multi => true
20
+ end
21
+
22
+ tickets = Set.new
23
+ Array(opts[:release_branch]).each { |release_branch|
24
+ opts[:ticket].each { |ticketRefAndChangesets|
25
+ ticket, *changesets = *ticketRefAndChangesets
26
+ tickets << Ticket.new(ticket, changesets, opts[:wc_root_path], release_branch)
27
+ }
28
+ Mergeinator.new(opts[:wc_root_path], release_branch, tickets).mergeStuff
29
+ }
@@ -0,0 +1,6 @@
1
+ begin
2
+ myPath = File.expand_path(File.dirname(__FILE__))
3
+ libPath = "#{myPath}/bnr_tools"
4
+ $: << myPath unless $:.include?(myPath)
5
+ $: << libPath unless $:.include?(libPath)
6
+ end
@@ -0,0 +1,60 @@
1
+ require 'svn_commands'
2
+ require 'digg_module'
3
+
4
+ class Changeset
5
+ include Comparable
6
+ attr_reader :revision
7
+ attr_accessor :wcBasePath, :releaseBranch
8
+ def initialize(rev, wc_base_path=SvnCommands::DIGG_DEFAULT_WC_PATH, release_branch="9.4")
9
+ @revision = Integer(rev)
10
+ @modified = {}
11
+ @affectedModules = {}
12
+ self.wcBasePath=wc_base_path
13
+ self.releaseBranch=release_branch
14
+ end
15
+
16
+ def modifiedPaths(relativeStartPath = self.wcBasePath)
17
+ @modified[relativeStartPath] ||= begin
18
+ SvnCommands::Log.new(relativeStartPath,"-r #{self.revision}", true).entries.first.paths.map {|p| p.to_s}
19
+ rescue
20
+ []
21
+ end
22
+ end
23
+
24
+ def affectedModulesbak(modulePath = "LOLz/trunk")
25
+ @affectedModules[modulePath] ||= self.modifiedPaths(modulePath).inject(Set.new) { |memo, modifiedPath|
26
+ (modifiedPath =~ /#{modulePath}\/([^\/]*)/) ? memo << DiggModule.new($1, self.wcBasePath, self.releaseBranch) : memo
27
+ }
28
+ end
29
+
30
+ def affectedModules(modulePath = "LOLz/trunk")
31
+ @affectedModules[modulePath] ||= begin
32
+ self.modifiedPaths(modulePath).inject(Set.new) { |memo, modifiedPath|
33
+ if modifiedPath =~ /#{modulePath}\/([^\/]*)/
34
+ moduleName = $1
35
+ unless (memo.detect{ |m| m.moduleName == moduleName })
36
+ memo << DiggModule.new($1, self.wcBasePath, self.releaseBranch)
37
+ end
38
+ end
39
+ memo
40
+ }
41
+ end
42
+ end
43
+
44
+ def to_s
45
+ "r#{revision}"
46
+ end
47
+
48
+ def <=>(other)
49
+ self.revision <=> other.revision
50
+ end
51
+
52
+ def hash
53
+ self.revision.hash
54
+ end
55
+
56
+ def eql?(other)
57
+ self.revision == other.revision
58
+ end
59
+
60
+ end
@@ -0,0 +1,103 @@
1
+ require 'svn_commands'
2
+ require 'version_number'
3
+ require 'fileutils'
4
+
5
+ class DiggModule
6
+ include Comparable
7
+ attr_reader :moduleName, :wcBasePath, :releaseBranch
8
+ def initialize(module_name, wc_base_path, release_branch)
9
+ @moduleName = module_name
10
+ @wcBasePath = wc_base_path
11
+ @releaseBranch = release_branch
12
+ end
13
+
14
+ def utilDir
15
+ @utilDir ||= begin
16
+ provisionalDir = "#{self.wcBasePath}/build/trunk"
17
+ unless File.exist? provisionalDir
18
+ SvnCommands::Update.new("build/trunk", nil, true, false, self.wcBasePath) # update the current working copy to be sure the dir is there
19
+ end
20
+ provisionalDir
21
+ end
22
+ end
23
+
24
+ def myCatDir
25
+ "#{self.wcBasePath}/LOLcat/branches/#{self.releaseBranch}"
26
+ end
27
+
28
+ def myDir
29
+ "#{self.myCatDir}/modules/#{self.moduleName}"
30
+ end
31
+
32
+ def getVersion
33
+ Dir.chdir(myDir) { |cwd|
34
+ VersionNumber.new(IO.popen(%Q{ #{self.utilDir}/version package.xml }).readlines.first.strip)
35
+ }
36
+ end
37
+
38
+ def updateVersion
39
+ Dir.chdir(myDir) { |cwd|
40
+ current_version = self.getVersion
41
+ new_version = block_given?() ? (yield current_version) : (current_version.next_after_patchlevel_increment)
42
+ puts IO.popen(%Q{ #{self.utilDir}/setversion package.xml #{new_version} }).readlines
43
+ self.updateManifest("#{myCatDir}/manifest/pear-common",new_version)
44
+ }
45
+ end
46
+
47
+ def updateManifest(manifest_path,new_version)
48
+ manifest_lines = File.readlines(manifest_path)
49
+ File.open(manifest_path, "w+") { |f|
50
+ manifest_lines.each { |line|
51
+ if line =~ /^pear.digg.internal\/#{self.moduleName}-/
52
+ f.puts("pear.digg.internal/#{self.moduleName}-#{new_version}")
53
+ else
54
+ f.puts(line)
55
+ end
56
+ }
57
+ }
58
+ end
59
+
60
+ def updateContents
61
+ Dir.chdir(myDir) { |cwd|
62
+ puts IO.popen(%Q{ #{self.utilDir}/update-contents package.xml }).readlines
63
+ }
64
+ end
65
+
66
+ def updateStability(stability="stable")
67
+ Dir.chdir(myDir) { |cwd|
68
+ puts IO.popen(%Q{ #{self.utilDir}/setstability package.xml #{stability} }).readlines
69
+ }
70
+ end
71
+
72
+ def buildPearPackage
73
+ Dir.chdir(myDir) { |cwd|
74
+ puts IO.popen(%Q{ pear package }).readlines
75
+ }
76
+ %Q{ #{self.utilDir}/upload #{myDir}/#{self.moduleName}-#{self.getVersion}.tgz }
77
+ end
78
+
79
+ def cleanupPackageXmlFormatting
80
+ Dir.chdir(myDir) { |cwd|
81
+ FileUtils.copy("package.xml","package.xml.unformatted")
82
+ puts IO.popen(%Q{ XMLLINT_INDENT=" " xmllint --format package.xml.unformatted > package.xml }).readlines
83
+ FileUtils.rm("package.xml.unformatted")
84
+ }
85
+ end
86
+
87
+ def to_s
88
+ self.moduleName
89
+ end
90
+
91
+ def <=>(other)
92
+ self.moduleName <=> other.moduleName
93
+ end
94
+
95
+ def eql?(other)
96
+ self.moduleName == other.moduleName
97
+ end
98
+
99
+ def hash
100
+ self.moduleName.hash
101
+ end
102
+
103
+ end
@@ -0,0 +1,129 @@
1
+ require 'svn_commands'
2
+ require 'version_number'
3
+ require 'highline/import'
4
+ require 'set'
5
+ require 'tempfile'
6
+
7
+ class Mergeinator
8
+ attr_reader :wcPath, :releaseBranchVersion
9
+ attr_accessor :catPath, :modulePath, :ticketsToMerge
10
+
11
+ def initialize(wc_path = SvnCommands::DIGG_DEFAULT_WC_PATH, release = VersionNumber.new(CURRENT_RELEASE_BRANCH,false), tickets=Set.new )
12
+ @wcPath = wc_path
13
+ @releaseBranchVersion = release.kind_of?(VersionNumber) ? release : VersionNumber.new(release,false)
14
+ self.ticketsToMerge = Set.new(Array(tickets))
15
+ self.catPath = "LOLcat/branches/#{releaseBranch}"
16
+ self.modulePath = "#{self.catPath}/modules"
17
+ end
18
+
19
+ def releaseBranch
20
+ "#{self.releaseBranchVersion.major}.#{self.releaseBranchVersion.minor}"
21
+ end
22
+
23
+ def branchWorkingDir
24
+ "#{self.wcPath}/LOLcat/branches/#{self.releaseBranch}"
25
+ end
26
+
27
+ def version
28
+ @versionToTag ||= begin
29
+ preExistingVersions = []
30
+ SvnCommands::Ls.new("LOLcat/tags").entries.each { |entry|
31
+ begin
32
+ entryVersion = VersionNumber.new(entry.name)
33
+ preExistingVersions << entryVersion
34
+ rescue Exception => e
35
+ puts "Exception processing entry: #{e}"
36
+ end
37
+ }
38
+ candidateVersions = preExistingVersions.find_all { |version| version.major == self.releaseBranchVersion.major && version.minor == self.releaseBranchVersion.minor }
39
+ highestCandidateVersion = candidateVersions.sort.last
40
+ puts "Highest existing version: #{highestCandidateVersion}"
41
+ ask("LOL{z,cat} version to tag?") { |q|
42
+ q.default = highestCandidateVersion.next_after_patchlevel_increment.to_s
43
+ q.validate = /#{self.releaseBranchVersion.major}\.#{self.releaseBranchVersion.minor}\.\d+/
44
+ }
45
+ end
46
+ end
47
+
48
+ def tagLOLCat
49
+ ref_msg = self.ticketsToMerge ? "Refs #{(self.ticketsToMerge.map {|t| "#{t}"}).join(", ")}" : "No tickets referenced"
50
+ if agree("References: #{ref_msg}\nOkay to tag branch #{self.releaseBranch} as version #{self.version}?")
51
+ SvnCommands.copy("LOLcat/branches/#{self.releaseBranch}","LOLcat/tags/#{version}", nil, nil, "Tagged LOLcat-#{version}. #{ref_msg}")
52
+ SvnCommands.copy("LOLz/branches/#{self.releaseBranch}","LOLz/tags/#{version}", nil, nil, "Tagged LOLz-#{version}. #{ref_msg}")
53
+ else
54
+ exit(1) unless agree("Oh. Well, would you like to keep going anyway, even though we can't commit anything?")
55
+ end
56
+ SvnCommands::Update.new("LOLcat/tags/#{version}",nil,true,true,self.wcPath) # shallowly checkout the new tag to ~/diggRepository/, no extra args for svn, force update
57
+ t = Tempfile.new("svn_externals").open { |tempfile|
58
+ tempfile.puts "modules svn+ssh://svn.digg.internal/repository/LOLz/tags/#{version}"
59
+ tempfile.puts "build svn+ssh://svn.digg.internal/repository/build/trunk"
60
+ }
61
+ cmd = "svn ps svn:externals --file #{t.path} #{SvnCommands::DIGG_DEFAULT_WC_PATH}/LOLcat/tags/#{version}"
62
+ puts "Running command : #{cmd}"
63
+ puts IO.popen(cmd).readlines
64
+ end
65
+
66
+ def svnMergeCommand(project, changeset)
67
+ "svn merge -c #{changeset.revision} svn+ssh://svn.digg.internal/repository/#{project}/trunk"
68
+ end
69
+
70
+ def mergeStuff
71
+ modules = Set.new
72
+ allChangesets = Set.new
73
+ self.cleanWorkingCopy
74
+ ticketsToMerge.each { |ticket|
75
+ allChangesets.merge(ticket.changesets)
76
+ modules.merge(ticket.affectedModules)
77
+ }
78
+ puts "Affected modules: #{modules.to_a.join(", ")}."
79
+ commitMessage = "Refs #{(ticketsToMerge.sort.map {|ticket| ticket.to_s(false)}).join(", ")} : Merged #{(allChangesets.sort.map {|c| c.to_s }).join(", ")} from trunk"
80
+ puts "Commit message = #{commitMessage}"
81
+ allChangesets.sort.each { |changeset|
82
+ # We could check paths and such, but that's just an extra step for the cat ...
83
+ SvnCommands.merge("LOLcat/trunk",self.catPath,changeset.revision,nil,nil,self.wcPath)
84
+ unless changeset.affectedModules("LOLz/trunk").empty? # OTOH, for modules, we already cached the information
85
+ SvnCommands.merge("LOLz/trunk",self.modulePath,changeset.revision,nil,nil,self.wcPath)
86
+ end
87
+ }
88
+
89
+ @module_upload_cmds = []
90
+ modules.each { |m|
91
+ m.updateVersion
92
+ m.updateContents
93
+ m.updateStability("stable")
94
+ m.cleanupPackageXmlFormatting
95
+ @module_upload_cmds << m.buildPearPackage
96
+ }
97
+
98
+ # Sanity check - spew the entire diff before committing it
99
+ Dir.chdir(self.branchWorkingDir) { |cwd|
100
+ puts IO.popen(%Q{ svn st && svn diff . modules }).readlines
101
+ @module_upload_cmds.each { |cmd| puts cmd }
102
+ puts "Before I commit - does everything look okay?"
103
+ if agree("Commit message: #{commitMessage}")
104
+ system %Q{ svn st | awk '/^\s?[MAD]/ { print $NF } ' | xargs svn commit -m'#{commitMessage}' }
105
+ else
106
+ exit(1) unless agree("Oh. Well, would you like to keep going anyway, even though we can't commit anything?")
107
+ end
108
+ }
109
+ tagLOLCat
110
+ if agree("Upload modified modules now?")
111
+ @module_upload_cmds.each { |cmd|
112
+ puts IO.popen(cmd).readlines
113
+ }
114
+ else
115
+ exit(1) unless agree("Oh. Well, would you like to keep going anyway, even though we can't commit anything?")
116
+ end
117
+ end
118
+
119
+ def cleanWorkingCopy(force=false)
120
+ if (force || agree("Clean working copy now?")) then
121
+ SvnCommands::Update.new(self.catPath, nil, true, false, self.wcPath) # update the current working copy to be sure the dir is there
122
+ Dir.chdir(branchWorkingDir) {
123
+ puts IO.popen(%Q{ svn revert -R . && svn revert -R modules && svn stat | grep "^\?" | cut -c8- | xargs rm -rf }).readlines
124
+ }
125
+ else
126
+ puts "Okay, trusting you ... it's all going to end in tears, I just know it ..."
127
+ end
128
+ end
129
+ end
@@ -0,0 +1,264 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ begin
4
+ require 'lib/bnr_tools'
5
+ rescue
6
+ end
7
+
8
+ require 'svn_xml'
9
+ require 'fileutils'
10
+ require 'open4'
11
+
12
+ module SvnCommands
13
+ DIGG_DEFAULT_SVN_URL="svn+ssh://svn.digg.internal/repository"
14
+ DIGG_DEFAULT_WC_PATH="#{ENV['HOME']}/diggRepository"
15
+
16
+ class SvnException < RuntimeError
17
+ def initialize(status_code, output)
18
+ @status_code = status_code
19
+ @output = output
20
+ end
21
+
22
+ def to_s
23
+ "Status code:#{@status_code} / output:#{@output} #{super}"
24
+ end
25
+ end
26
+
27
+ class << self
28
+ def svnVersion
29
+ @@svnVersion ||= VersionNumber.new(`svn --version --quiet`)
30
+ end
31
+
32
+ def extra_merge_flags
33
+ (Integer(svnVersion.major) >= 1 && Integer(svnVersion.minor) >= 5) ? ["--accept postpone"] : []
34
+ end
35
+
36
+ def new_cmd(command_string, expected_result_class=nil, max_retries=3)
37
+ puts "Executing: '#{command_string}'"
38
+ retry_count = 0
39
+ begin
40
+ out = ""
41
+ err = ""
42
+ status = Open4::popen4(command_string) do |pid, stdin, stdout, stderr|
43
+ stdin.close
44
+ out = stdout.read
45
+ err = stderr.read
46
+ end
47
+ unless status.exitstatus == 0
48
+ raise SvnException.new(status.exitstatus, "stdout: #{out}\n\nstderr: #{err}")
49
+ end
50
+ if (expected_result_class)
51
+ parsed = REXML::Document.new(out)
52
+ expected_result_class.new(parsed.elements[expected_result_class.expected_node_name])
53
+ else
54
+ nil
55
+ end
56
+ rescue Exception => e
57
+ if e.kind_of?(Interrupt)
58
+ exit(1)
59
+ elsif retry_count < max_retries
60
+ # puts "invocation failed with #{e.class} #{e} ... trying again"
61
+ retry_count += 1
62
+ retry
63
+ else
64
+ raise e
65
+ end
66
+ end
67
+ end
68
+
69
+ def copy(fromPath, toPath, extra_args=nil, working_copy_path=nil, commit_msg=nil, repository_base_url=DIGG_DEFAULT_SVN_URL)
70
+ path_base = working_copy_path || repository_base_url
71
+ full_from_path = "#{path_base.chomp("/")}/#{fromPath}"
72
+ full_to_path = "#{path_base.chomp("/")}/#{toPath}"
73
+ if (working_copy_path)
74
+ SvnCommands.new_cmd("svn cp #{Array(extra_args).join(" ")} \"#{full_from_path}\" \"#{full_to_path}\"",nil,1)
75
+ else
76
+ if (commit_msg)
77
+ SvnCommands.new_cmd("svn cp #{Array(extra_args).join(" ")} \"#{full_from_path}\" \"#{full_to_path}\" -m\"#{commit_msg}\"",nil,1)
78
+ else
79
+ raise SvnException.new(-1, "Without a commit message, I can't svn cp a remote URL. Sorry.")
80
+ end
81
+ end
82
+ end
83
+
84
+ def merge(fromPath, toPath, start_rev, end_rev = nil, extra_args=nil, working_copy_path=nil, repository_base_url=DIGG_DEFAULT_SVN_URL)
85
+ extra_args = (Array(extra_args) << SvnCommands.extra_merge_flags).compact
86
+ full_from_path = "#{repository_base_url.chomp("/")}/#{fromPath}"
87
+ full_to_path = "#{working_copy_path.chomp("/")}/#{toPath}"
88
+ rev_spec = begin
89
+ if end_rev.nil?() || Integer(end_rev) == 0
90
+ "-c #{Integer(start_rev)}"
91
+ else
92
+ "-r#{Integer(start_rev)}:#{Integer(end_rev)}"
93
+ end
94
+ end
95
+ SvnCommands.new_cmd("svn merge #{rev_spec} #{extra_args.join(" ")} \"#{full_from_path}\" \"#{full_to_path}\"")
96
+ end
97
+
98
+ def sync(fromPath, toPath, working_copy_path, extra_args=nil, repository_base_url=DIGG_DEFAULT_SVN_URL)
99
+ extra_args = (Array(extra_args) << SvnCommands.extra_merge_flags).compact
100
+ repository_from_path = "#{repository_base_url.chomp("/")}/#{fromPath}"
101
+ repository_to_path = "#{repository_base_url.chomp("/")}/#{toPath}"
102
+ wc_to_path = "#{working_copy_path.chomp("/")}/#{toPath}"
103
+ SvnCommands.new_cmd("svn merge #{extra_args.join(" ")} \"#{repository_to_path}\" \"#{repository_from_path}\" \"#{wc_to_path}\"")
104
+ end
105
+
106
+ def mkdir(path, commit_msg=nil, working_copy_path=nil, repository_base_url=DIGG_DEFAULT_SVN_URL)
107
+ path_base = working_copy_path || repository_base_url
108
+ full_path = "#{path_base.chomp("/")}/#{path}"
109
+ extra_args = (Array(extra_args) << SvnCommands.extra_merge_flags).compact
110
+ if (working_copy_path)
111
+ SvnCommands.new_cmd("svn mkdir #{full_path}")
112
+ else
113
+ if (commit_msg)
114
+ SvnCommands.new_cmd("svn mkdir #{full_path} -m'#{commit_msg}'")
115
+ else
116
+ raise SvnException.new(-1, "No commit message specified; cannot mkdir directly in the repository")
117
+ end
118
+ end
119
+ end
120
+
121
+ end
122
+
123
+ class PathOp
124
+ attr_accessor :fullpath, :entries
125
+ def initialize(relativePath, repository_base_url=DIGG_DEFAULT_SVN_URL)
126
+ @fullpath=relativePath.nil? ? repository_base_url : "#{repository_base_url}/#{relativePath}"
127
+ end
128
+ end
129
+
130
+ class Ls < PathOp
131
+ attr_accessor :lists
132
+ @@all_lists ||= {}
133
+ def initialize(relativePath=nil, extra_args=nil, force_update=false, repository_base_url=DIGG_DEFAULT_SVN_URL)
134
+ super(relativePath, repository_base_url)
135
+ cmd = "svn ls --xml #{Array(extra_args).join(" ")} #{fullpath}"
136
+ @@all_lists[fullpath] = if (force_update || @@all_lists[fullpath].nil?)
137
+ SvnCommands.new_cmd(cmd, SvnXml::Lists)
138
+ else
139
+ @@all_lists[fullpath]
140
+ end
141
+ @lists = @@all_lists[fullpath]
142
+ @entries = @lists.entries
143
+ end
144
+ end
145
+
146
+ class Log < PathOp
147
+ attr_reader :entries
148
+ @@all_entries ||= {}
149
+ def initialize(relativePath=nil, extra_args=nil, force_update=false, repository_base_url=DIGG_DEFAULT_SVN_URL)
150
+ super(relativePath, repository_base_url)
151
+ @@all_entries[fullpath] = if (force_update || @@all_entries[fullpath].nil?)
152
+ SvnCommands.new_cmd("svn log -vv --xml #{Array(extra_args).join(" ")} #{fullpath}", SvnXml::Log).entries
153
+ else
154
+ @@all_entries[fullpath]
155
+ end
156
+ @entries = @@all_entries[fullpath]
157
+ end
158
+
159
+ def messages
160
+ @messages ||= self.entries.collect { |entry| entry.msg }
161
+ end
162
+
163
+ def revisions
164
+ @revisions ||= self.entries.collect { |entry| entry.revision }
165
+ end
166
+
167
+ def oldest_revision
168
+ self.revisions.sort.first
169
+ end
170
+
171
+ def newest_revision
172
+ self.revisions.sort.last
173
+ end
174
+ end
175
+
176
+ class Update < PathOp
177
+ @@shallow_paths ||= {}
178
+ @@recursive_paths ||= {}
179
+
180
+ def updatedShallow?(path)
181
+ path_parent = File.dirname(path)
182
+ if [".","/",""].include?(path_parent)
183
+ @@shallow_paths[path] || false
184
+ else
185
+ @@shallow_paths[path] || updatedRecursive?(path_parent)
186
+ end
187
+ end
188
+
189
+ def updatedRecursive?(path)
190
+ path_parent = File.dirname(path)
191
+ if [".","/",""].include? path_parent
192
+ @@recursive_paths[path] || false
193
+ else
194
+ @@recursive_paths[path] || updatedRecursive?(path_parent)
195
+ end
196
+ end
197
+
198
+ def alreadyUpdated?(shallowUpdate)
199
+ if shallowUpdate
200
+ updatedShallow?(fullpath)
201
+ else
202
+ updatedRecursive?(fullpath)
203
+ end
204
+ end
205
+
206
+ def pretty_hash(h)
207
+ if h.kind_of?(Hash)
208
+ h.inject(nil) { |memo, kv|
209
+ key = kv[0]
210
+ val = kv[1]
211
+ (memo ? "#{memo}; " : "") + "#{key}=#{pretty_hash(val)}"
212
+ }
213
+ else
214
+ h.to_s
215
+ end
216
+ end
217
+
218
+ def updateCache(shallow)
219
+ if shallow
220
+ @@shallow_paths[fullpath] ||= 0
221
+ @@shallow_paths[fullpath] += 1
222
+ #puts "Updated shallow cache; current contents #{pretty_hash(@@shallow_paths)}"
223
+ else
224
+ @@recursive_paths[fullpath] ||= 0
225
+ @@recursive_paths[fullpath] += 1
226
+ #puts "Updated recursive cache; current contents #{pretty_hash(@@recursive_paths)}"
227
+ end
228
+ end
229
+
230
+ def ensureWorkingCopyExistsAt(aPath)
231
+ out = `svn info #{aPath}`
232
+ unless $? == 0
233
+ FileUtils.mkdir_p(aPath)
234
+ SvnCommands.new_cmd("svn co -N svn+ssh://svn.digg.internal/repository/ #{aPath.chomp("/")}")
235
+ end
236
+ end
237
+
238
+ def initialize(path, extra_args=nil, force_update=false, shallow=false, working_copy_path=DIGG_DEFAULT_WC_PATH)
239
+ super(path, working_copy_path)
240
+ cache_hit = alreadyUpdated?(shallow)
241
+ #puts "Update requested on #{path} - cache hit = #{cache_hit}"
242
+ if force_update || cache_hit == false || cache_hit.nil?
243
+ argPile = Array(extra_args)
244
+ if (shallow)
245
+ argPile << "-N"
246
+ end
247
+ argPile << fullpath
248
+ if (path == nil || path.size < 2)
249
+ ensureWorkingCopyExistsAt(working_copy_path)
250
+ else
251
+ wc_fullpath = "#{working_copy_path}/#{path}"
252
+ unless (File.exist? wc_fullpath)
253
+ # make sure our parent dir is in good shape ...
254
+ #puts "Hm, #{fullpath} doesn't exist. Calling checkOut (shallow) on #{File.dirname(relative_path)} ..."
255
+ SvnCommands::Update.new(File.dirname(path), nil, force_update, true, working_copy_path)
256
+ end
257
+ end
258
+ SvnCommands.new_cmd("svn up #{argPile.join(" ")}")
259
+ end
260
+ updateCache(shallow)
261
+ end
262
+ end
263
+
264
+ end