Made CruxUtils::Port.open return the port.
[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 initialize(dir)
24                 @dir = dir
25
26                 @attribs = Hash.new { |h, k| h[k] = "" }
27
28                 @attribs[:dependencies] = Dependencies.new
29                 @attribs[:source] = Sources.new
30                 @attribs[:build] = BuildFunc.new
31
32                 read
33         end
34
35         def method_missing(meth, *args)
36                 if meth.to_s.match(/=$/) then
37                         m2 = meth.to_s[0...-1].to_sym
38                         @attribs[m2] = (args.length < 2 ? args.first : args)
39                 else
40                         @attribs[meth]
41                 end
42         end
43
44         def dependencies
45                 @attribs[:dependencies].uniq!
46                 @attribs[:dependencies]
47         end
48
49         def has_footprint?
50                 File.exist?(footprint)
51         end
52
53         def has_md5sum?
54                 File.exist?(md5sum)
55         end
56
57         def write
58                 Tempfile.open("pkgfile") do |file|
59                         COMMENT_MAP.each do |key, symbol|
60                                 value = @attribs[symbol]
61                                 next if value.empty?
62
63                                 file << "# #{key}: " << value << "\n"
64                         end
65
66                         file << "\n"
67
68                         vars = [:name, :version, :release, :source]
69                         vars.each do |var|
70                                 file << "#{var}=" <<
71                                         @attribs[var] << "\n"
72                         end
73
74                         file << "\n" << build << "\n"
75                         file.flush
76
77                         FileUtils.cp(file.path, pkgfile)
78                 end
79         end
80
81         private
82         def read
83                 vars = [:name, :version, :release]
84                 section = :comments
85
86                 cmt_map = OHash.new.replace(COMMENT_MAP)
87
88                 File.read(pkgfile).split("\n").each do |line|
89                         line.chomp!
90
91                         cmt_map.each do |key, symbol|
92                                 md = line.match(/^#\s*#{key}: (.+)$/)
93                                 unless md.nil?
94                                         @attribs[symbol].replace(md.captures.first.strip)
95                                         cmt_map.delete(key)
96                                 end
97                         end
98
99                         vars.each do |var|
100                                 md = line.match(/^#{var}=(.+)$/)
101                                 unless md.nil?
102                                         @attribs[var] = $1.strip
103                                         vars.delete(key)
104                                 end
105                         end
106
107                         # handle source array
108                         section = :void if line.match(/^\s*$/) && section != :build
109
110                         if section == :source && line.match(/(.+)\)$/)
111                                 @attribs[:source] << $1.strip
112                         elsif section == :source && line.match(/(.+)\\$/)
113                                 @attribs[:source] << $1.strip
114                         elsif line.match(/^source=\((.+)\)$/)
115                                 @attribs[:source] << $1.strip
116                         elsif line.match(/^source=\((.+)\\$/)
117                                 @attribs[:source] << $1.strip
118                                 section = :source
119                         end
120
121                         section = :end unless line.match(/^\}/).nil?
122                         if section == :build
123                                 # remove initial indentation
124                                 tmp = line.sub(/^(    |\t)/, "")
125
126                                 @attribs[:build] << (tmp || "")
127                         end
128                         section = :build unless line.match(/^build/).nil?
129                 end
130         end
131
132         def pkgfile
133                 File.join(@dir, "Pkgfile")
134         end
135
136         def footprint
137                 File.join(@dir, ".footprint")
138         end
139
140         def md5sum
141                 File.join(@dir, ".md5sum")
142         end
143 end
144
145 class Dependencies < Array
146         def to_s
147                 uniq.join(", ")
148         end
149
150         def replace(arg)
151                 if arg.is_a?(Array)
152                         super
153                 else
154                         clear
155
156                         arg.split(", ").each { |d| self << d.strip }
157                 end
158
159                 uniq!
160
161                 self
162         end
163 end
164
165 class Sources < Array
166         def to_s
167                 indent = " " * "source=(".length
168                 "(" + join(" \\\n" + indent) + ")"
169         end
170 end
171
172 class BuildFunc < Array
173         def to_s
174                 inject("build() {\n") do |a, line|
175                         if line != ""
176                                 line = "\t" + line
177                         end
178
179                         a << line << "\n"
180                         a
181                 end + "}"
182         end
183 end
184
185 end