Added CruxUtils::Port.find. Patch by Rene Lengwinat.
[ruby-cruxutils.git] / lib / cruxutils / port.rb
1 require "cruxutils/ohash.rb"
2 require "tempfile"
3 require "fileutils"
4
5 module CruxUtils
6
7 class Port
8         COMMENT_MAP = OHash.new
9         COMMENT_MAP["Description"] = :description
10         COMMENT_MAP["URL"] = :url
11         COMMENT_MAP["Packager"] = :packager
12         COMMENT_MAP["Maintainer"] = :maintainer
13         COMMENT_MAP["Depends on"] = :dependencies
14         COMMENT_MAP["Group"] = :group
15         COMMENT_MAP["Nice to have"] = :nice_to_have
16
17         def Port.open(dir)
18                 tmp = Port.new(dir)
19                 yield tmp
20                 tmp
21         end
22
23         def Port.find(pattern)
24                 PORTDIRS.inject([]) do |memo, pd|
25                         tmp = Dir["#{pd}/#{pattern}"].map { |d| Port.new(d) }
26                         memo.concat(tmp)
27                 end
28         end
29
30         def initialize(dir)
31                 @dir = dir
32
33                 @attribs = Hash.new { |h, k| h[k] = "" }
34
35                 @attribs[:dependencies] = Dependencies.new
36                 @attribs[:source] = Sources.new
37                 @attribs[:build] = BuildFunc.new
38
39                 read
40         end
41
42         def method_missing(meth, *args)
43                 if meth.to_s.match(/=$/) then
44                         m2 = meth.to_s[0...-1].to_sym
45                         @attribs[m2] = (args.length < 2 ? args.first : args)
46                 else
47                         @attribs[meth]
48                 end
49         end
50
51         def dependencies
52                 @attribs[:dependencies].uniq!
53                 @attribs[:dependencies]
54         end
55
56         def has_footprint?
57                 File.exist?(footprint)
58         end
59
60         def has_md5sum?
61                 File.exist?(md5sum)
62         end
63
64         def write
65                 Tempfile.open("pkgfile") do |file|
66                         COMMENT_MAP.each do |key, symbol|
67                                 value = @attribs[symbol]
68                                 next if value.empty?
69
70                                 file << "# #{key}: " << value << "\n"
71                         end
72
73                         file << "\n"
74
75                         vars = [:name, :version, :release, :source]
76                         vars.each do |var|
77                                 file << "#{var}=" <<
78                                         @attribs[var] << "\n"
79                         end
80
81                         file << "\n" << build << "\n"
82                         file.flush
83
84                         FileUtils.cp(file.path, pkgfile)
85                 end
86         end
87
88         private
89         def read
90                 vars = [:name, :version, :release]
91                 section = :comments
92
93                 cmt_map = OHash.new.replace(COMMENT_MAP)
94
95                 File.read(pkgfile).split("\n").each do |line|
96                         line.chomp!
97
98                         cmt_map.each do |key, symbol|
99                                 md = line.match(/^#\s*#{key}: (.+)$/)
100                                 unless md.nil?
101                                         @attribs[symbol].replace(md.captures.first.strip)
102                                         cmt_map.delete(key)
103                                 end
104                         end
105
106                         vars.each do |var|
107                                 md = line.match(/^#{var}=(.+)$/)
108                                 unless md.nil?
109                                         @attribs[var] = $1.strip
110                                         vars.delete(key)
111                                 end
112                         end
113
114                         # handle source array
115                         section = :void if line.match(/^\s*$/) && section != :build
116
117                         if section == :source && line.match(/(.+)\)$/)
118                                 @attribs[:source] << $1.strip
119                         elsif section == :source && line.match(/(.+)\\$/)
120                                 @attribs[:source] << $1.strip
121                         elsif line.match(/^source=\((.+)\)$/)
122                                 @attribs[:source] << $1.strip
123                         elsif line.match(/^source=\((.+)\\$/)
124                                 @attribs[:source] << $1.strip
125                                 section = :source
126                         end
127
128                         section = :end unless line.match(/^\}/).nil?
129                         if section == :build
130                                 # remove initial indentation
131                                 tmp = line.sub(/^(    |\t)/, "")
132
133                                 @attribs[:build] << (tmp || "")
134                         end
135                         section = :build unless line.match(/^build/).nil?
136                 end
137         end
138
139         def pkgfile
140                 File.join(@dir, "Pkgfile")
141         end
142
143         def footprint
144                 File.join(@dir, ".footprint")
145         end
146
147         def md5sum
148                 File.join(@dir, ".md5sum")
149         end
150 end
151
152 class Dependencies < Array
153         def to_s
154                 uniq.join(", ")
155         end
156
157         def replace(arg)
158                 if arg.is_a?(Array)
159                         super
160                 else
161                         clear
162
163                         arg.split(", ").each { |d| self << d.strip }
164                 end
165
166                 uniq!
167
168                 self
169         end
170 end
171
172 class Sources < Array
173         def to_s
174                 indent = " " * "source=(".length
175                 "(" + join(" \\\n" + indent) + ")"
176         end
177 end
178
179 class BuildFunc < Array
180         def to_s
181                 inject("build() {\n") do |a, line|
182                         if line != ""
183                                 line = "\t" + line
184                         end
185
186                         a << line << "\n"
187                         a
188                 end + "}"
189         end
190 end
191
192 end