drupid 1.0.1 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,4 +1,6 @@
1
- # Copyright (c) 2012 Lifepillar
1
+ # -*- coding: ascii -*-
2
+
3
+ # Copyright (c) 2012-2013 Lifepillar
2
4
  #
3
5
  # Permission is hereby granted, free of charge, to any person obtaining a copy
4
6
  # of this software and associated documentation files (the "Software"), to deal
@@ -1,6 +1,6 @@
1
1
  # -*- coding: utf-8 -*-
2
2
 
3
- # Copyright (c) 2012 Lifepillar
3
+ # Copyright (c) 2012-2013 Lifepillar
4
4
  #
5
5
  # Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  # of this software and associated documentation files (the "Software"), to deal
@@ -45,7 +45,8 @@ module Drupid
45
45
  end
46
46
 
47
47
  def fetch
48
- cached_location.rmtree if cached_location.exist?
48
+ debug "Cached location: #{cached_location}"
49
+ dont_debug { cached_location.rmtree if cached_location.exist? }
49
50
  super
50
51
  end
51
52
  end # Library
@@ -1,6 +1,6 @@
1
1
  # -*- coding: utf-8 -*-
2
2
 
3
- # Copyright (c) 2012 Lifepillar
3
+ # Copyright (c) 2012-2013 Lifepillar
4
4
  #
5
5
  # Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  # of this software and associated documentation files (the "Software"), to deal
@@ -1,6 +1,6 @@
1
1
  # -*- coding: utf-8 -*-
2
2
 
3
- # Copyright (c) 2012 Lifepillar
3
+ # Copyright (c) 2012-2013 Lifepillar
4
4
  #
5
5
  # Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  # of this software and associated documentation files (the "Software"), to deal
@@ -39,6 +39,7 @@ module Drupid
39
39
  # Downloads the patch into the current directory.
40
40
  def fetch
41
41
  dst = Pathname.pwd+File.basename(@url.to_s)
42
+ blah "Fetching patch..."
42
43
  begin
43
44
  curl @url.to_s, '-o', dst
44
45
  rescue
@@ -1,6 +1,6 @@
1
1
  # -*- coding: utf-8 -*-
2
2
 
3
- # Copyright (c) 2012 Lifepillar
3
+ # Copyright (c) 2012-2013 Lifepillar
4
4
  #
5
5
  # Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  # of this software and associated documentation files (the "Software"), to deal
@@ -30,10 +30,10 @@ module Drupid
30
30
  # or nil if this platform does not contain Drupal core.
31
31
  attr :drupal_project
32
32
  # The path for contrib modules and themes (e.g., 'sites/all'),
33
- # relative to #path.
33
+ # relative to #local_path.
34
34
  attr_accessor :contrib_path
35
35
  # The path to the sites directory (default: 'sites'), relative
36
- # relative to #path.
36
+ # relative to #local_path.
37
37
  attr :sites_dir
38
38
 
39
39
  # Creates a new platform object for the Drupal installation at the
@@ -50,7 +50,7 @@ module Drupid
50
50
  # Returns the version of Drupal core in this platform, or
51
51
  # nil if the version cannot be determined.
52
52
  def version
53
- if @drupal_project and @drupal_project.has_version?
53
+ if (@drupal_project and @drupal_project.has_version?) or load_drupal_version
54
54
  return @drupal_project.version
55
55
  end
56
56
  return nil
@@ -134,13 +134,9 @@ module Drupid
134
134
 
135
135
  # Retrieves information about Drupal core in this platform.
136
136
  def analyze_drupal_core
137
+ debug 'Analyzing Drupal Core...'
137
138
  @drupal_project = nil
138
- vers = Drupid::Drush.drupal_version(local_path)
139
- if vers
140
- core = vers.match(/(\d+)\./)[1].to_i
141
- @drupal_project = Drupid::Project.new('drupal', core, vers)
142
- @drupal_project.local_path = self.local_path
143
- end
139
+ load_drupal_version
144
140
  end
145
141
 
146
142
  # Extracts information about the projects in this platform.
@@ -230,5 +226,29 @@ module Drupid
230
226
  graph.write_to_graphic_file('svg')
231
227
  end
232
228
 
229
+ private
230
+
231
+ def load_drupal_version
232
+ # Drupal 7 stores VERSION in bootstrap.inc. Drupal 8 moved that to /core/includes.
233
+ bootstrap_files = ['core/includes/bootstrap.inc', 'includes/bootstrap.inc', 'modules/system/system.module']
234
+ bootstrap_files.each do |bf|
235
+ f = self.local_path+bf
236
+ next unless f.exist?
237
+ f.open('r').each_line do |l|
238
+ if l =~ /define.*'VERSION'.*'(.+)'/
239
+ v = $1
240
+ debug "Drupal version detected: #{v}"
241
+ core = v.match(/^(\d+)\./)[1].to_i
242
+ @drupal_project = Drupid::Project.new('drupal', core, v)
243
+ @drupal_project.local_path = self.local_path
244
+ debug "Drupal platform has version: #{@drupal_project.version} (core: #{@drupal_project.version.core})"
245
+ return true
246
+ end
247
+ end
248
+ end
249
+ debug "Unable to detect version of Drupal at #{self.local_path}"
250
+ return false
251
+ end
252
+
233
253
  end # Platform
234
254
  end # Drupid
@@ -1,6 +1,6 @@
1
1
  # -*- coding: utf-8 -*-
2
2
 
3
- # Copyright (c) 2012 Lifepillar
3
+ # Copyright (c) 2012-2013 Lifepillar
4
4
  #
5
5
  # Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  # of this software and associated documentation files (the "Software"), to deal
@@ -1,6 +1,6 @@
1
1
  # -*- coding: utf-8 -*-
2
2
 
3
- # Copyright (c) 2012 Lifepillar
3
+ # Copyright (c) 2012-2013 Lifepillar
4
4
  #
5
5
  # Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  # of this software and associated documentation files (the "Software"), to deal
@@ -19,6 +19,8 @@
19
19
  # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
20
  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
21
  # SOFTWARE.
22
+ require 'nokogiri'
23
+ require 'open-uri'
22
24
 
23
25
  module Drupid
24
26
 
@@ -272,6 +274,7 @@ module Drupid
272
274
  @version = vers ? Version.from_s(@core.to_s + '-' + vers) : nil
273
275
  @proj_type = ('drupal' == @name) ? 'drupal' : nil
274
276
  @info_file = nil
277
+ @release_xml = nil
275
278
  end
276
279
 
277
280
  # Returns true if a version is specified for this project, false otherwise.
@@ -289,6 +292,7 @@ module Drupid
289
292
  # The argument must be a String object or a Drupid::Version object.
290
293
  # For the syntax of the String argument, see Drupid::Version.
291
294
  def version=(new_version)
295
+ return @version = nil if new_version.nil?
292
296
  if new_version.is_a?(Version)
293
297
  temp_version = new_version
294
298
  elsif new_version.is_a?(String)
@@ -297,24 +301,65 @@ module Drupid
297
301
  else
298
302
  raise NotDrupalVersionError
299
303
  end
300
- raise NotDrupalVersionError, "Incompatible version for project #{extended_name}: #{temp_version.long}" if temp_version.core != core
304
+ raise NotDrupalVersionError, "Incompatible version for project #{self.extended_name}: #{temp_version.long}" if temp_version.core != self.core
301
305
  @version = temp_version
302
306
  end
303
307
 
304
- # Updates the version of this project to the latest recommended release;
305
- # if no recommended release is available, tries to retrieve the version
306
- # of the latest supported release; if no supported release is found, the version
307
- # of this project is not modified.
308
- # Raises an error if no release history for the project is found (presumably
309
- # because no such project exists on drupal.org).
308
+ # Updates the version of this project to the latest (stable) release.
310
309
  #
311
- # *Requires:* a network connection.
310
+ # Retrieves the release information for this project from http://updates.drupal.org.
311
+ #
312
+ # See also: Drupid::Project.best_release
312
313
  def update_version
313
- v = recommended_release
314
- v = supported_release unless v
315
- if v
316
- self.version = core.to_s + '-' + v
317
- debug "Version updated: #{extended_name}"
314
+ self.fetch_release_history if @release_xml.nil?
315
+ return self.version unless @release_xml
316
+ version_list = []
317
+ version_nodes = @release_xml.xpath("/project/releases/release[status='published']/version")
318
+ version_nodes.each do |n|
319
+ v = n.child.to_s
320
+ # Remove version specifications that do not start with self.core.
321
+ # This seemingly superfluous test is needed because, for example,
322
+ # imce-7.x has a 'master' version (oh my!).
323
+ next if v !~ /^#{self.core.to_i}\./
324
+ v.sub!("#{self.core}-", '') unless self.drupal?
325
+ version_list.push(Version.new(self.core, v))
326
+ end
327
+ self.version = self.best_release(version_list)
328
+ debug "Version updated: #{extended_name}"
329
+ end
330
+
331
+ # Updates the download URL for the current version of this project.
332
+ #
333
+ # Retrieves the release information for this project from http://updates.drupal.org.
334
+ def update_download_url
335
+ self.fetch_release_history if @release_xml.nil?
336
+ return if @release_xml.nil?
337
+ if @release_xml.at_xpath('/project/releases/release/files/file/variant').nil?
338
+ variant = ''
339
+ else
340
+ variant = "[variant='profile-only']"
341
+ end
342
+ v = self.drupal? ? self.version.short : self.version.long
343
+ url_node = @release_xml.at_xpath("/project/releases/release[status='published'][version='#{v}']/files/file#{variant}/url")
344
+ if url_node.nil?
345
+ owarn "Could not get download URL from http://updates.drupal.org for #{extended_name}"
346
+ else
347
+ self.download_url = url_node.child.to_s
348
+ end
349
+ end
350
+
351
+ # Fetches the release history for this project from http://updates.drupal.org.
352
+ def fetch_release_history
353
+ begin
354
+ debug "Getting release history from http://updates.drupal.org/release-history/#{self.name}/#{self.core}"
355
+ dont_debug do
356
+ @release_xml = Nokogiri::XML(open("http://updates.drupal.org/release-history/#{self.name}/#{self.core}"))
357
+ end
358
+ debug "Release history retrieved"
359
+ rescue Exception
360
+ owarn "Could not get release history for #{self.extended_name}"
361
+ blah e
362
+ @release_xml = nil
318
363
  end
319
364
  end
320
365
 
@@ -437,39 +482,33 @@ module Drupid
437
482
  end
438
483
 
439
484
  def fetch
440
- # Try to get the latest version if:
441
- # (1) the project is not local;
442
- # (2) it does not have a version already;
443
- # (3) no download type has been explicitly given.
444
- unless has_version? or download_url =~ /file:\/\// or download_type
445
- update_version
485
+ if self.version.nil? and download_url.nil? and download_type.nil?
486
+ debug "Updating version of #{self.extended_name}"
487
+ self.update_version
446
488
  end
447
489
  # If the project has no version we fetch it even if it is cached.
448
490
  # If the project has a download type, we fetch it even if it is cached
449
491
  # (say the download type is 'git' and the revision is changed in the
450
492
  # makefile, then the cached project must be updated accordingly).
451
- if has_version? and !download_type and cached_location.exist?
452
- @local_path = cached_location
453
- debug "#{extended_name} is cached"
493
+ if self.has_version? and self.download_type.nil? and self.cached_location.exist?
494
+ @local_path = self.cached_location
495
+ debug "#{self.extended_name} is cached"
454
496
  else
455
- blah "Fetching #{extended_name}"
456
- if download_type
457
- if download_url
458
- src = download_url
459
- elsif 'git' == download_type # Download from git.drupal.org
460
- src = "http://git.drupal.org/project/#{name}.git"
461
- else
462
- raise "No download URL specified for #{extended_name}" unless download_url
463
- end
464
- else
465
- src = extended_name
497
+ blah "Fetching #{self.extended_name}"
498
+ if 'git' == self.download_type and self.download_url.nil?
499
+ self.download_url = "http://git.drupal.org/project/#{name}.git"
466
500
  end
467
- downloader = Drupid.makeDownloader src, cached_location.dirname.to_s, cached_location.basename.to_s, download_specs.merge({:type => download_type})
501
+ self.update_download_url if self.download_url.nil?
502
+ raise "No download URL specified for #{self.extended_name}" unless self.download_url
503
+ downloader = Drupid.makeDownloader self.download_url.to_s,
504
+ self.cached_location.dirname.to_s,
505
+ self.cached_location.basename.to_s,
506
+ self.download_specs.merge({:type => download_type})
468
507
  downloader.fetch
469
508
  downloader.stage
470
509
  @local_path = downloader.staged_path
471
510
  end
472
- reload_project_info unless drupal?
511
+ self.reload_project_info unless self.drupal?
473
512
  end
474
513
 
475
514
  # Returns the relative path where this project should be installed
@@ -529,34 +568,20 @@ module Drupid
529
568
  super(tgt, args)
530
569
  end
531
570
 
532
- # Returns the version of the latest recommended release of this project
533
- # as a string, or nil if no recommended release can be found
534
- # or the project does not exist at drupal.org.
535
- #
536
- # *Requires:* a network connection.
537
- #
538
- # See also: Drupid::Drush.pm_releases, Drupid::Project.supported_release
539
- def recommended_release
540
- output = Drush.pm_releases(name + '-' + core.to_s)
541
- return unless output =~ /RELEASES FOR/
542
- rl = Drush.recommended_release(output)
543
- return rl.sub(/^#{core}-/, '') if rl
544
- return nil
545
- end
546
571
 
547
- # Returns the version of the latest supported release
548
- # as a string, or nil if no supported release can be found
549
- # or the project does not exist at drupal.org.
550
- #
551
- # *Requires:* a network connection.
552
- #
553
- # See also: Drupid::Drush.pm_releases, Drupid::Project.recommended_release
554
- def supported_release
555
- output = Drush.pm_releases(name + '-' + core.to_s)
556
- return nil unless output =~ /RELEASES FOR/
557
- rl = Drush.supported_release(output)
558
- return rl.sub(/^#{core}-/, '') if rl
559
- return nil
572
+ # Returns the "best" version among those in the given list.
573
+ # Returns the current version of the project when version_list is empty.
574
+ def best_release version_list
575
+ if self.has_version? # Exclude releases older than the current one
576
+ version_list = version_list.select { |v| v >= self.version }
577
+ end
578
+ return self.version if version_list.empty?
579
+ stable_releases = version_list.select { |v| v.stable? }
580
+ if stable_releases.empty?
581
+ version_list.max { |a,b| a.better b }
582
+ else
583
+ stable_releases.max { |a,b| a.better b }
584
+ end
560
585
  end
561
586
 
562
587
  end # Project
@@ -1,6 +1,6 @@
1
1
  # -*- coding: utf-8 -*-
2
2
 
3
- # Copyright (c) 2012 Lifepillar
3
+ # Copyright (c) 2012-2013 Lifepillar
4
4
  #
5
5
  # Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  # of this software and associated documentation files (the "Software"), to deal
@@ -36,11 +36,12 @@ module Drupid
36
36
 
37
37
  # Creates a new updater for a given makefile and a given platform.
38
38
  # For multisite platforms, optionally specify a site to synchronize.
39
- def initialize(makefile, platform, site_name = nil)
39
+ def initialize(makefile, platform, options = { :site => nil, :force => false })
40
40
  @makefile = makefile
41
41
  @platform = platform
42
- @site = site_name
42
+ @site = options[:site]
43
43
  @log = Log.new
44
+ @force_changes = options[:force]
44
45
  #
45
46
  @libraries_paths = Array.new
46
47
  @core_projects = Array.new
@@ -210,10 +211,20 @@ module Drupid
210
211
  pending_delete = @platform.project_names - processed
211
212
  pending_delete.each do |p|
212
213
  proj = platform.get_project(p)
213
- if proj.installed?(site)
214
- log.error "#{proj.extended_name} cannot be deleted because it is installed"
215
- end
216
214
  log.action(DeleteAction.new(platform, proj))
215
+ if which('drush').nil?
216
+ if @force_changes
217
+ owarn "Forcing deletion."
218
+ else
219
+ log.error "#{proj.extended_name}: use --force to force deletion or install Drush >=6.0."
220
+ end
221
+ elsif proj.installed?(site)
222
+ if @force_changes
223
+ owarn "Deleting an installed/enabled project."
224
+ else
225
+ log.error "#{proj.extended_name} cannot be deleted because it is installed"
226
+ end
227
+ end
217
228
  end
218
229
  end
219
230
 
@@ -243,26 +254,35 @@ module Drupid
243
254
  if @platform.local_path + new_path != platform_project.local_path
244
255
  log.action(MoveAction.new(@platform, platform_project, new_path))
245
256
  if (@platform.local_path + new_path).exist?
246
- log.error("#{new_path} already exists. Use --force to overwrite.")
257
+ if @force_changes
258
+ owarn "Overwriting existing path: #{new_path}"
259
+ else
260
+ log.error("#{new_path} already exists. Use --force to overwrite.")
261
+ end
247
262
  end
248
263
  end
249
264
  # Compare versions and log suitable actions
250
265
  _compare_versions project, platform_project
251
-
252
- # If analyzing the platform does not detect the project (e.g., Fusion),
253
- # we try to see if the directory exists where it is supposed to be.
254
- elsif (@platform.local_path + @platform.dest_path(project)).exist?
255
- begin
256
- platform_project = PlatformProject.new(@platform, @platform.local_path + @platform.dest_path(project))
257
- rescue => ex
258
- log.error("#{platform_project.relative_path} exists, but cannot be analyzed: #{ex}")
259
- log.action(UpdateProjectAction.new(@platform, project))
266
+ else
267
+ # If analyzing the platform does not allow us to detect the project (e.g., Fusion),
268
+ # we try to see if the directory exists where it is supposed to be.
269
+ proj_path = @platform.local_path + @platform.dest_path(project)
270
+ if proj_path.exist?
271
+ begin
272
+ platform_project = PlatformProject.new(@platform, proj_path)
273
+ _compare_versions project, platform_project
274
+ rescue => ex
275
+ log.action(UpdateProjectAction.new(@platform, project))
276
+ if @force_changes
277
+ owarn "Overwriting existing path: #{proj_path}"
278
+ else
279
+ log.error("#{proj_path} exists, but was not recognized as a project (use --force to overwrite it): #{ex}")
280
+ end
281
+ end
282
+ else # new project
283
+ log.action(InstallProjectAction.new(@platform, project))
260
284
  end
261
- _compare_versions project, platform_project
262
- else # new project
263
- log.action(InstallProjectAction.new(@platform, project))
264
285
  end
265
-
266
286
  return (not has_makefile)
267
287
  end
268
288
 
@@ -308,7 +328,7 @@ module Drupid
308
328
  odie "Failed to verify the integrity of library #{lib.extended_name}: #{ex}"
309
329
  end
310
330
  if diff.empty?
311
- log.notice("[OK] #{lib.extended_name} (#{relpath})")
331
+ log.notice("#{Tty.white}[OK]#{Tty.reset} #{lib.extended_name} (#{relpath})")
312
332
  else
313
333
  log.action(UpdateLibraryAction.new(platform, lib))
314
334
  log.notice(diff.join("\n"))
@@ -337,6 +357,29 @@ module Drupid
337
357
  @derivative_builds.clear
338
358
  end
339
359
 
360
+ # Updates Drupal's database using <tt>drush updatedb</tt>.
361
+ # If #site is defined, then updates only the specified site; otherwise,
362
+ # iterates over all Platform#site_names and updates each one in turn.
363
+ #
364
+ # Returns true upon success, false otherwise.
365
+ def updatedb
366
+ ohai "Updating Drupal database..."
367
+ blah "Platform: #{self.platform.local_path}"
368
+ res = true
369
+ site_list = (self.site) ? [self.site] : self.platform.site_names
370
+ site_list.each do |s|
371
+ site_path = self.platform.sites_path + s
372
+ debug "Site path: #{site_path}"
373
+ unless site_path.exist?
374
+ debug "Skipping #{site_path} because it does not exist."
375
+ next
376
+ end
377
+ blah "Updating site: #{s}"
378
+ res = Drush.updatedb(site_path) && res
379
+ end
380
+ return res
381
+ end
382
+
340
383
  private
341
384
 
342
385
  # Returns true if the given component is successfully cached and patched;
@@ -372,25 +415,43 @@ module Drupid
372
415
  end
373
416
  p = (makefile_project.drupal?) ? '' : ' (' + (platform.contrib_path + makefile_project.target_path).to_s + ')'
374
417
  if diff.empty?
375
- @log.notice("[OK] #{platform_project.extended_name}#{p}")
418
+ @log.notice("#{Tty.white}[OK]#{Tty.reset} #{platform_project.extended_name}#{p}")
376
419
  elsif makefile_project.has_patches?
377
420
  log.action(update_action)
378
421
  log.notice "#{makefile_project.extended_name}#{p} will be patched"
379
422
  log.notice(diff.join("\n"))
380
423
  else
381
- log.error("#{platform_project.extended_name}#{p}: mismatch with cached copy:\n" + diff.join("\n"))
382
424
  log.action(update_action)
425
+ if @force_changes
426
+ owarn "Mismatch with cached copy: overwriting local copy."
427
+ else
428
+ log.error("#{platform_project.extended_name}#{p}: mismatch with cached copy:\n" + diff.join("\n"))
429
+ end
383
430
  end
384
431
  when 1 # upgrade
385
432
  log.action(update_action)
386
433
  when -1 # downgrade
387
- log.action(update_action)
388
- if platform_project.drupal?
434
+ log.action(UpdateProjectAction.new(platform, makefile_project, :downgrade => true))
435
+ if which('drush').nil?
436
+ if @force_changes
437
+ owarn "Forcing downgrade."
438
+ else
439
+ log.error("#{platform_project.extended_name}: use --force to downgrade or install Drush >=6.0.")
440
+ end
441
+ elsif platform_project.drupal?
389
442
  if @platform.bootstrapped?
390
- log.error("#{platform_project.extended_name} cannot be downgraded because it is bootstrapped")
443
+ if @force_changes
444
+ owarn "Downgrading a bootstrapped Drupal platform."
445
+ else
446
+ log.error("#{platform_project.extended_name} cannot be downgraded because it is bootstrapped (use --force to override)")
447
+ end
391
448
  end
392
449
  elsif platform_project.installed?(site)
393
- log.error("#{platform_project.extended_name}#{p} must be uninstalled before downgrading")
450
+ if @force_changes
451
+ owarn "Downgrading an installed/enabled project."
452
+ else
453
+ log.error("#{platform_project.extended_name}#{p} must be uninstalled before downgrading (use --force to override)")
454
+ end
394
455
  end
395
456
  when nil # One or both projects have no version
396
457
  # Check whether the content of the projects is consistent
@@ -400,12 +461,16 @@ module Drupid
400
461
  odie "Failed to verify the integrity of #{component.extended_name}: #{ex}"
401
462
  end
402
463
  if diff.empty?
403
- log.notice("[OK] #{platform_project.extended_name}#{p}")
464
+ log.notice("#{Tty.white}[OK]#{Tty.reset} #{platform_project.extended_name}#{p}")
404
465
  else
405
466
  log.action(update_action)
406
467
  log.notice(diff.join("\n"))
407
468
  if platform_project.has_version? and (not makefile_project.has_version?)
408
- log.error("Cannot upgrade #{makefile_project.name} from known version to unknown version")
469
+ if @force_changes
470
+ owarn "Upgrading #{makefile_project.name} to unknown version."
471
+ else
472
+ log.error("Cannot upgrade #{makefile_project.name} from known version to unknown version")
473
+ end
409
474
  end
410
475
  end
411
476
  end
@@ -453,7 +518,7 @@ module Drupid
453
518
  # Adds an error message to the log.
454
519
  def error(msg)
455
520
  @errors << msg
456
- puts @errors.last
521
+ ofail @errors.last
457
522
  end
458
523
 
459
524
  # Returns true if this log contains error messages;
@@ -465,7 +530,7 @@ module Drupid
465
530
  # Adds a warning to the log.
466
531
  def warning(msg)
467
532
  @warnings << msg
468
- puts @warnings.last
533
+ owarn @warnings.last
469
534
  end
470
535
 
471
536
  def warnings?
@@ -523,17 +588,19 @@ module Drupid
523
588
 
524
589
 
525
590
  class UpdateProjectAction < AbstractAction
526
- def initialize(p, proj)
591
+ def initialize p, proj, opts = { :downgrade => false }
527
592
  raise "#{proj.extended_name} does not exist locally" unless proj.exist?
528
593
  raise "Unknown type for #{proj.extended_name}" unless proj.proj_type
529
- super
594
+ @downgrade = opts[:downgrade]
595
+ super(p, proj)
530
596
  end
531
597
 
532
598
  def msg
599
+ label = 'Update'
533
600
  if old_project = platform.get_project(component.name)
534
- "#{Tty.blue}[Update]#{Tty.white} #{old_project.extended_name} => #{component.extended_name}#{Tty.reset} (#{platform.dest_path(component)})"
601
+ "#{Tty.blue}[#{label}]#{Tty.white} #{component.name}: #{old_project.version.long} => #{component.version.long}#{Tty.reset} (#{platform.dest_path(component)})"
535
602
  else
536
- "#{Tty.blue}[Update]#{Tty.white} #{component.extended_name}#{Tty.reset} (#{platform.dest_path(component)})"
603
+ "#{Tty.blue}[#{label}]#{Tty.white} #{component.name}: => #{component.version.long}#{Tty.reset} (#{platform.dest_path(component)})"
537
604
  end
538
605
  end
539
606
 
@@ -572,8 +639,7 @@ module Drupid
572
639
  args << '--delete'
573
640
  component.ignore_paths.each { |p| args << "--exclude=#{p}" }
574
641
  dst_path = platform.local_path + platform.dest_path(component)
575
- debug "Pathname.mkpath may raise harmless exceptions"
576
- dst_path.mkpath unless dst_path.exist?
642
+ dont_debug { dst_path.mkpath }
577
643
  args << component.local_path.to_s + '/'
578
644
  args << dst_path.to_s + '/'
579
645
  begin
@@ -616,8 +682,7 @@ module Drupid
616
682
  args << '--delete'
617
683
  component.ignore_paths.each { |p| args << "--exclude=#{p}" }
618
684
  dst_path = platform.local_path + platform.contrib_path + component.target_path
619
- debug "Pathname.mkpath may raise harmless exceptions"
620
- dst_path.mkpath unless dst_path.exist?
685
+ dont_debug { dst_path.mkpath }
621
686
  args << component.local_path.to_s + '/'
622
687
  args << dst_path.to_s + '/'
623
688
  begin
@@ -631,7 +696,7 @@ module Drupid
631
696
 
632
697
  class InstallLibraryAction < UpdateLibraryAction
633
698
  def msg
634
- "#{Tty.blue}[Install]#{Tty.white} Library #{component.extended_name}#{Tty.reset} (#{platform.contrib_path + component.target_path})"
699
+ "#{Tty.blue}[Install]#{Tty.white} Library #{component.extended_name}#{Tty.reset} (#{platform.contrib_path + component.target_path})"
635
700
  end
636
701
  end
637
702
 
@@ -648,10 +713,10 @@ module Drupid
648
713
  debug "Moving #{component.local_path} to #{dst}"
649
714
  if dst.exist?
650
715
  debug "#{dst} already exists, it will be deleted"
651
- dst.rmtree
716
+ dont_debug { dst.rmtree }
652
717
  end
653
- dst.parent.mkpath
654
- FileUtils.mv component.local_path.to_s, dst.to_s
718
+ dont_debug { dst.parent.mkpath }
719
+ dont_debug { FileUtils.mv component.local_path.to_s, dst.to_s }
655
720
  else
656
721
  blah "Cannot move #{component.local_path.relative_path_from(platform.local_path)}\n" +
657
722
  "(It does not exist any longer)"
@@ -661,14 +726,15 @@ module Drupid
661
726
 
662
727
  def msg
663
728
  src = component.local_path.relative_path_from(platform.local_path)
664
- "#{Tty.blue}[Move]#{Tty.reset} From #{src} to #{@destination}"
729
+ "#{Tty.blue}[Move]#{Tty.white} #{component.extended_name}:#{Tty.reset} #{src} => #{@destination}"
665
730
  end
666
731
  end # MoveAction
667
732
 
668
733
 
669
734
  class DeleteAction < AbstractAction
670
735
  def fire!
671
- component.local_path.rmtree if component.local_path.exist?
736
+ debug "Deleting #{component.local_path}"
737
+ dont_debug { component.local_path.rmtree if component.local_path.exist? }
672
738
  @pending = false
673
739
  end
674
740