drupid 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,185 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ # Copyright (c) 2012 Lifepillar
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the "Software"), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in all
13
+ # copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ # SOFTWARE.
22
+
23
+ module Drupid
24
+
25
+ # A wrapper around drush.
26
+ module Drush extend Drupid::Utils
27
+
28
+ DRUSH = `which drush`.strip
29
+
30
+ def self.drush *args
31
+ runBabyRun DRUSH, args
32
+ end
33
+
34
+ # Executes 'drush core-status' at the given path and
35
+ # returns the output of the command.
36
+ def self.status path, options = {}
37
+ output = nil
38
+ FileUtils.cd(path) do
39
+ output = drush 'core-status', '--pipe'
40
+ end
41
+ output
42
+ end
43
+
44
+ # Executes 'drush pm-releases --all' for the given project and
45
+ # returns the output of the command.
46
+ def self.pm_releases project_name, options = {}
47
+ drush 'pm-releases', '--all', project_name
48
+ end
49
+
50
+ # Parses the output of 'drush pm-releases' and returns
51
+ # the version of the latest recommended release, or nil
52
+ # if no such release exists.
53
+ def self.recommended_release pm_releases_output
54
+ pm_releases_output.each_line do |l|
55
+ return $~[1] if (l.match(/^\s*([^\s]+).*Recommended/))
56
+ end
57
+ nil
58
+ end
59
+
60
+ # Parses the output of 'drush pm-releases' and returns
61
+ # the version of the latest supported release, or nil
62
+ # if no such release exists.
63
+ def self.supported_release pm_releases_output
64
+ pm_releases_output.each_line do |l|
65
+ return $~[1] if (l.match(/^\s*([^\s]+).*Supported/))
66
+ end
67
+ nil
68
+ end
69
+
70
+ # Executes 'drush pm-download <project_name>' and
71
+ # returns the output of the command.
72
+ # If :working_dir is set to an existing directory, move into that directory before
73
+ # executing the command.
74
+ #
75
+ # Options: source, destination, working_dir
76
+ def self.pm_download project_name, options = {}
77
+ args = ['pm-download', '-y']
78
+ args << "--source=#{options[:source]}" if options[:source]
79
+ args << "--destination\=#{options[:destination]}" if options[:destination]
80
+ args << "--variant=profile-only"
81
+ args << "--verbose" if $VERBOSE
82
+ args << project_name
83
+ if options[:working_dir] and File.directory?(options[:working_dir])
84
+ wd = options[:working_dir]
85
+ else
86
+ wd = FileUtils.pwd
87
+ end
88
+ output = nil
89
+ FileUtils.cd(wd) do
90
+ output = runBabyRun DRUSH, args, :redirect_stderr_to_stdout => true
91
+ end
92
+ output
93
+ end
94
+
95
+ # Parses the output of 'drush pm-download' and returns
96
+ # the path to the downloaded project, or nil
97
+ # if the path cannot be determined.
98
+ def self.download_path pm_download_output
99
+ pm_download_output.match(/^\s*Project.+downloaded to *(.\[.+[\n\r])?\s*(.+)\./)
100
+ return File.expand_path($~[2]) if $~
101
+ return nil
102
+ end
103
+
104
+ # Parses the output of 'drush pm-download' and returns
105
+ # the version of the downloaded project, or nil
106
+ # if the version cannot be determined.
107
+ def self.downloaded_version pm_download_output
108
+ pm_download_output.match(/^\s*Project.+\((.+)\) +downloaded +to/)
109
+ return $~[1] if $~
110
+ return nil
111
+ end
112
+
113
+ # Executes 'drush pm-info' at the given path and with an
114
+ # optional list of projects.
115
+ # Returns the output of the command.
116
+ def self.pm_info path, projects = [], options = {}
117
+ output = nil
118
+ args = Array.new
119
+ args << 'pm-info'
120
+ args << projects.join(' ') unless nil != projects and projects.empty?
121
+ FileUtils.cd(path) do
122
+ output = runBabyRun DRUSH, args, :redirect_stderr_to_stdout => true
123
+ end
124
+ output
125
+ end
126
+
127
+ # Returns the version of Drupal (e.g., '7.12')
128
+ # if the given path contains Drupal;
129
+ # returns nil otherwise.
130
+ def self.drupal_version path, options = {}
131
+ st = self.status(path, options)
132
+ return nil unless st.match(/drupal_version=(\d+\.\d+)/)
133
+ return $~[1]
134
+ end
135
+
136
+ # Returns true if a Drupal's site is bootstrapped at the given path;
137
+ # returns false otherwise.
138
+ def self.bootstrapped?(path, options = {})
139
+ st = self.status(path, options)
140
+ st.match(/drupal_bootstrap=Successful/) ? true : false
141
+ end
142
+
143
+ # Returns true if the project at the given path is an enabled theme
144
+ # or an installed (enabled or disabled) module in the given site;
145
+ # returns false otherwise. The project's path must be relative
146
+ # to the Drupal installation (e.g., 'sites/all/modules').
147
+ # Note that the project path is necessary because, in general,
148
+ # there may be several copies of the same modules at different locations
149
+ # within a platform (in 'sites/all', in 'profiles/' and in site-specific locations).
150
+ #
151
+ # Options: verbose
152
+ def self.installed?(site_path, project_name, project_path, options = {})
153
+ st = ''
154
+ begin
155
+ st = self.pm_info(site_path, [project_name], options)
156
+ rescue # site not fully bootstrapped
157
+ return false
158
+ end
159
+ return false unless st.match(/Path +: +#{project_path}/)
160
+ return false unless st.match(/Type +: +([^\s]+)/)
161
+ type = $~[1]
162
+ return false unless st.match(/Status +: +(.+)$/)
163
+ project_status = $~[1]
164
+ ('module' == type and project_status !~ /not installed/) or
165
+ ('theme' == type and project_status =~ /^enabled/)
166
+ end
167
+
168
+ # Executes 'drush make' and returns the output of the command.
169
+ #
170
+ # Options: contrib_path, nocore, dry, verbose
171
+ def self.make(makefile, target, options = {})
172
+ args = Array.new
173
+ args << 'make'
174
+ args << '-y'
175
+ args << '--no-core' if options[:nocore]
176
+ args << "--contrib-destination=#{options[:contrib_path]}" if options[:contrib_path]
177
+ args << "--no-patch-txt"
178
+ args << makefile
179
+ args << target
180
+ drush(*args)
181
+ end
182
+
183
+ end # module Drush
184
+
185
+ end # Drupid
@@ -0,0 +1,114 @@
1
+ # Copyright (c) 2012 Lifepillar
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in all
11
+ # copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ # SOFTWARE.
20
+
21
+ # Portions Copyright 2009-2011 Max Howell and other contributors.
22
+ #
23
+ # Redistribution and use in source and binary forms, with or without
24
+ # modification, are permitted provided that the following conditions
25
+ # are met:
26
+ #
27
+ # 1. Redistributions of source code must retain the above copyright
28
+ # notice, this list of conditions and the following disclaimer.
29
+ # 2. Redistributions in binary form must reproduce the above copyright
30
+ # notice, this list of conditions and the following disclaimer in the
31
+ # documentation and/or other materials provided with the distribution.
32
+ #
33
+ # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
34
+ # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
35
+ # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
36
+ # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
37
+ # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
38
+ # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
39
+ # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
40
+ # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
41
+ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
42
+ # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
43
+
44
+ require 'pathname'
45
+
46
+ # Code borrowed from Homebrew ;)
47
+ class Pathname
48
+ def compression_type
49
+ return nil if self.directory?
50
+ # Don't treat jars or wars as compressed
51
+ return nil if self.extname == '.jar'
52
+ return nil if self.extname == '.war'
53
+
54
+ # OS X installer package
55
+ return :pkg if self.extname == '.pkg'
56
+
57
+ # Get enough of the file to detect common file types
58
+ # POSIX tar magic has a 257 byte offset
59
+ magic_bytes = nil
60
+ File.open(self) { |f| magic_bytes = f.read(262) }
61
+
62
+ # magic numbers stolen from /usr/share/file/magic/
63
+ case magic_bytes
64
+ when /^PK\003\004/ then :zip
65
+ when /^\037\213/ then :gzip
66
+ when /^BZh/ then :bzip2
67
+ when /^\037\235/ then :compress
68
+ when /^.{257}ustar/ then :tar
69
+ when /^\xFD7zXZ\x00/ then :xz
70
+ when /^Rar!/ then :rar
71
+ else
72
+ # Assume it is not an archive
73
+ nil
74
+ end
75
+ end
76
+
77
+ def cd
78
+ Dir.chdir(self) { yield }
79
+ end
80
+
81
+ # Copies a file to another location or
82
+ # the content of a directory into the specified directory.
83
+ def ditto dst
84
+ d = Pathname.new(dst)
85
+ if file?
86
+ FileUtils.cp to_s, d.to_s, :verbose => $DEBUG
87
+ return (d.directory?) ? d+basename : d
88
+ else
89
+ d.mkpath
90
+ FileUtils.cp_r to_s + '/.', d.to_s, :verbose => $DEBUG
91
+ return d
92
+ end
93
+ end
94
+
95
+ # extended to support common double extensions
96
+ alias extname_old extname
97
+ def extname
98
+ /(\.(tar|cpio)\.(gz|bz2|xz|Z))$/.match to_s
99
+ return $1 if $1
100
+ return File.extname(to_s)
101
+ end
102
+
103
+ # Pathname in Ruby 1.8.x does not define #sub_ext.
104
+ unless self.method_defined? :sub_ext
105
+ # Return a pathname which the extension of the basename is substituted by
106
+ # <i>repl</i>.
107
+ #
108
+ # If self has no extension part, <i>repl</i> is appended.
109
+ def sub_ext(repl)
110
+ ext = File.extname(@path)
111
+ self.class.new(@path.chomp(ext) + repl)
112
+ end
113
+ end
114
+ end # Pathname
@@ -0,0 +1,52 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ # Copyright (c) 2012 Lifepillar
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the "Software"), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in all
13
+ # copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ # SOFTWARE.
22
+
23
+ module Drupid
24
+ class Library < Component
25
+
26
+ def initialize name
27
+ super
28
+ self.download_type = 'file' # Default download type
29
+ @destination = nil
30
+ end
31
+
32
+ def destination
33
+ return Pathname.new('libraries') unless @destination
34
+ return Pathname.new(@destination)
35
+ end
36
+
37
+ def destination=(d)
38
+ @destination = d
39
+ end
40
+
41
+ # Returns the relative path where this library should be installed
42
+ # within a platform. This is 'libraries/#name' by default.
43
+ def target_path
44
+ return destination + subdir + directory_name
45
+ end
46
+
47
+ def fetch
48
+ cached_location.rmtree if cached_location.exist?
49
+ super
50
+ end
51
+ end # Library
52
+ end # Drupid