aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorhisham <hisham@9ca3f7c1-7366-0410-b1a3-b5c78f85698c>2009-04-16 22:20:49 +0000
committerhisham <hisham@9ca3f7c1-7366-0410-b1a3-b5c78f85698c>2009-04-16 22:20:49 +0000
commit6df8be18495cf4c09509bca3a38f44f6afe7ceec (patch)
tree441643b799bf66dd5660b5cdf0679f71fee8a448 /src
parent4f15619eabf3b47853406bbb5b52f5878121df44 (diff)
downloadluarocks-6df8be18495cf4c09509bca3a38f44f6afe7ceec.tar.gz
luarocks-6df8be18495cf4c09509bca3a38f44f6afe7ceec.tar.bz2
luarocks-6df8be18495cf4c09509bca3a38f44f6afe7ceec.zip
Split 3rd-party-tool-dependant parts
git-svn-id: http://luarocks.org/svn/luarocks/trunk@9 9ca3f7c1-7366-0410-b1a3-b5c78f85698c
Diffstat (limited to 'src')
-rw-r--r--src/luarocks/fs/unix/tools.lua314
-rw-r--r--src/luarocks/fs/win32/tools.lua230
2 files changed, 544 insertions, 0 deletions
diff --git a/src/luarocks/fs/unix/tools.lua b/src/luarocks/fs/unix/tools.lua
new file mode 100644
index 00000000..fdec7869
--- /dev/null
+++ b/src/luarocks/fs/unix/tools.lua
@@ -0,0 +1,314 @@
1
2--- fs operations implemented with third-party tools for Unix platform abstractions.
3module("luarocks.fs.unix.tools", package.seeall)
4
5local fs = require("luarocks.fs")
6
7local cfg = require("luarocks.cfg")
8
9dir_stack = {}
10
11--- Run the given command.
12-- The command is executed in the current directory in the dir stack.
13-- @param cmd string: No quoting/escaping is applied to the command.
14-- @return boolean: true if command succeeds (status code 0), false
15-- otherwise.
16function execute_string(cmd)
17 if os.execute("cd " .. fs.Q(fs.current_dir()) .. " && " .. cmd) == 0 then
18 return true
19 else
20 return false
21 end
22end
23
24--- Obtain current directory.
25-- Uses the module's internal dir stack.
26-- @return string: the absolute pathname of the current directory.
27function current_dir()
28 local current = os.getenv("PWD")
29 if not current then
30 local pipe = io.popen("pwd")
31 current = pipe:read("*l")
32 pipe:close()
33 end
34 for _, d in ipairs(fs.dir_stack) do
35 current = fs.absolute_name(d, current)
36 end
37 return current
38end
39
40--- Change the current directory.
41-- Uses the module's internal dir stack. This does not have exact
42-- semantics of chdir, as it does not handle errors the same way,
43-- but works well for our purposes for now.
44-- @param d string: The directory to switch to.
45function change_dir(d)
46 assert(type(d) == "string")
47 table.insert(fs.dir_stack, d)
48end
49
50--- Change directory to root.
51-- Allows leaving a directory (e.g. for deleting it) in
52-- a crossplatform way.
53function change_dir_to_root()
54 table.insert(fs.dir_stack, "/")
55end
56
57--- Change working directory to the previous in the dir stack.
58function pop_dir()
59 local d = table.remove(fs.dir_stack)
60 return d ~= nil
61end
62
63--- Create a directory if it does not already exist.
64-- If any of the higher levels in the path name does not exist
65-- too, they are created as well.
66-- @param d string: pathname of directory to create.
67-- @return boolean: true on success, false on failure.
68function make_dir(d)
69 assert(d)
70 return fs.execute("mkdir -p", d)
71end
72
73--- Remove a directory if it is empty.
74-- Does not return errors (for example, if directory is not empty or
75-- if already does not exist)
76-- @param dir string: pathname of directory to remove.
77function remove_dir_if_empty(d)
78 assert(d)
79 fs.execute_string("rmdir "..fs.Q(d).." 1> /dev/null 2> /dev/null")
80end
81
82--- Copy a file.
83-- @param src string: Pathname of source
84-- @param dest string: Pathname of destination
85-- @return boolean or (boolean, string): true on success, false on failure,
86-- plus an error message.
87function copy(src, dest)
88 assert(src and dest)
89 if fs.execute("cp", src, dest) then
90 return true
91 else
92 return false, "Failed copying "..src.." to "..dest
93 end
94end
95
96--- Recursively copy the contents of a directory.
97-- @param src string: Pathname of source
98-- @param dest string: Pathname of destination
99-- @return boolean or (boolean, string): true on success, false on failure,
100-- plus an error message.
101function copy_contents(src, dest)
102 assert(src and dest)
103 if fs.execute_string("cp -pPR "..fs.Q(src).."/* "..fs.Q(dest).." 1> /dev/null 2>/dev/null") then
104 return true
105 else
106 return false, "Failed copying "..src.." to "..dest
107 end
108end
109--- Delete a file or a directory and all its contents.
110-- For safety, this only accepts absolute paths.
111-- @param arg string: Pathname of source
112-- @return boolean: true on success, false on failure.
113function delete(arg)
114 assert(arg)
115 assert(arg:sub(1,1) == "/")
116 return fs.execute_string("rm -rf " .. fs.Q(arg) .. " 1> /dev/null 2>/dev/null")
117end
118
119--- List the contents of a directory.
120-- @param at string or nil: directory to list (will be the current
121-- directory if none is given).
122-- @return table: an array of strings with the filenames representing
123-- the contents of a directory.
124function list_dir(at)
125 assert(type(at) == "string" or not at)
126 if not at then
127 at = fs.current_dir()
128 end
129 if not fs.is_dir(at) then
130 return {}
131 end
132 local result = {}
133 local pipe = io.popen("cd "..fs.Q(at).." && ls")
134 for file in pipe:lines() do
135 table.insert(result, file)
136 end
137 pipe:close()
138 return result
139end
140
141--- Recursively scan the contents of a directory.
142-- @param at string or nil: directory to scan (will be the current
143-- directory if none is given).
144-- @return table: an array of strings with the filenames representing
145-- the contents of a directory.
146function find(at)
147 assert(type(at) == "string" or not at)
148 if not at then
149 at = fs.current_dir()
150 end
151 if not fs.is_dir(at) then
152 return {}
153 end
154 local result = {}
155 local pipe = io.popen("cd "..fs.Q(at).." && find * 2>/dev/null")
156 for file in pipe:lines() do
157 table.insert(result, file)
158 end
159 pipe:close()
160 return result
161end
162
163--- Compress files in a .zip archive.
164-- @param zipfile string: pathname of .zip archive to be created.
165-- @param ... Filenames to be stored in the archive are given as
166-- additional arguments.
167-- @return boolean: true on success, false on failure.
168function zip(zipfile, ...)
169 return fs.execute("zip -r", zipfile, ...)
170end
171
172--- Uncompress files from a .zip archive.
173-- @param zipfile string: pathname of .zip archive to be extracted.
174-- @return boolean: true on success, false on failure.
175function unzip(zipfile)
176 assert(zipfile)
177 return fs.execute("unzip", zipfile)
178end
179
180--- Test for existance of a file.
181-- @param file string: filename to test
182-- @return boolean: true if file exists, false otherwise.
183function exists(file)
184 assert(file)
185 return fs.execute("test -r", file)
186end
187
188--- Test is file/dir is writable.
189-- @param file string: filename to test
190-- @return boolean: true if file exists, false otherwise.
191function is_writable(file)
192 assert(file)
193 return fs.execute("test -w", file)
194end
195
196--- Test is pathname is a directory.
197-- @param file string: pathname to test
198-- @return boolean: true if it is a directory, false otherwise.
199function is_dir(file)
200 assert(file)
201 return fs.execute("test -d", file)
202end
203
204--- Test is pathname is a regular file.
205-- @param file string: pathname to test
206-- @return boolean: true if it is a regular file, false otherwise.
207function is_file(file)
208 assert(file)
209 return fs.execute("test -f", file)
210end
211
212--- Download a remote file.
213-- @param url string: URL to be fetched.
214-- @param filename string or nil: this function attempts to detect the
215-- resulting local filename of the remote file as the basename of the URL;
216-- if that is not correct (due to a redirection, for example), the local
217-- filename can be given explicitly as this second argument.
218-- @return boolean: true on success, false on failure.
219function download(url, filename)
220 assert(type(url) == "string")
221 assert(type(filename) == "string" or not filename)
222
223 if cfg.downloader == "wget" then
224 local wget_cmd = "wget --user-agent="..cfg.user_agent.." --quiet --continue "
225 if filename then
226 return fs.execute(wget_cmd.." --output-document ", filename, url)
227 else
228 return fs.execute(wget_cmd, url)
229 end
230 elseif cfg.downloader == "curl" then
231 filename = filename or dir.base_name(url)
232 return fs.execute_string("curl --user-agent "..cfg.user_agent.." "..fs.Q(url).." 2> /dev/null 1> "..fs.Q(filename))
233 end
234end
235
236function chmod(pathname, mode)
237 return fs.execute("chmod "..mode, pathname)
238end
239
240--- Apply a patch.
241-- @param patchname string: The filename of the patch.
242function apply_patch(patchname)
243 return fs.execute("patch -p1 -f -i ", patchname)
244end
245
246--- Unpack an archive.
247-- Extract the contents of an archive, detecting its format by
248-- filename extension.
249-- @param archive string: Filename of archive.
250-- @return boolean or (boolean, string): true on success, false and an error message on failure.
251function unpack_archive(archive)
252 assert(type(archive) == "string")
253
254 local ok
255 if archive:match("%.tar%.gz$") or archive:match("%.tgz$") then
256 -- ok = fs.execute("tar zxvpf ", archive)
257 ok = fs.execute_string("gunzip -c "..archive.."|tar -xf -")
258 elseif archive:match("%.tar%.bz2$") then
259 -- ok = fs.execute("tar jxvpf ", archive)
260 ok = fs.execute_string("bunzip2 -c "..archive.."|tar -xf -")
261 elseif archive:match("%.zip$") then
262 ok = fs.execute("unzip ", archive)
263 elseif archive:match("%.lua$") or archive:match("%.c$") then
264 -- Ignore .lua and .c files; they don't need to be extracted.
265 return true
266 else
267 local ext = archive:match(".*(%..*)")
268 return false, "Unrecognized filename extension "..(ext or "")
269 end
270 if not ok then
271 return false, "Failed extracting "..archive
272 end
273 return true
274end
275
276--- Check the MD5 checksum for a file.
277-- @param file string: The file to be checked.
278-- @param md5sum string: The string with the expected MD5 checksum.
279-- @return boolean: true if the MD5 checksum for 'file' equals 'md5sum', false if not
280-- or if it could not perform the check for any reason.
281function check_md5(file, md5sum)
282 file = fs.absolute_name(file)
283 local computed
284 if cfg.md5checker == "md5sum" then
285 local pipe = io.popen("md5sum "..file)
286 computed = pipe:read("*l"):gsub("[^%x]+", "")
287 pipe:close()
288 if computed then
289 computed = computed:sub(1,32)
290 end
291 elseif cfg.md5checker == "openssl" then
292 local pipe = io.popen("openssl md5 "..file)
293 computed = pipe:read("*l")
294 pipe:close()
295 if computed then
296 computed = computed:sub(-32)
297 end
298 elseif cfg.md5checker == "md5" then
299 local pipe = io.popen("md5 "..file)
300 computed = pipe:read("*l")
301 pipe:close()
302 if computed then
303 computed = computed:sub(-32)
304 end
305 end
306 if not computed then
307 return false
308 end
309 if computed:match("^"..md5sum) then
310 return true
311 else
312 return false
313 end
314end
diff --git a/src/luarocks/fs/win32/tools.lua b/src/luarocks/fs/win32/tools.lua
new file mode 100644
index 00000000..9f7b829b
--- /dev/null
+++ b/src/luarocks/fs/win32/tools.lua
@@ -0,0 +1,230 @@
1
2--- fs operations implemented with third-party tools for Windows platform abstractions.
3-- Download http://unxutils.sourceforge.net/ for Windows GNU utilities
4-- used by this module.
5module("luarocks.fs.win32.tools", package.seeall)
6
7local fs = require("luarocks.fs")
8
9local function command_at(directory, cmd)
10 local drive = directory:match("^([A-Za-z]:)")
11 cmd = "cd " .. fs.Q(directory) .. " & " .. cmd
12 if drive then
13 cmd = drive .. " & " .. cmd
14 end
15 return cmd
16end
17
18--- Test for existance of a file.
19-- @param file string: filename to test
20-- @return boolean: true if file exists, false otherwise.
21function exists(file)
22 assert(file)
23 return fs.execute("if not exist " .. fs.Q(file) ..
24 " invalidcommandname 2>NUL 1>NUL")
25end
26
27--- Test is pathname is a directory.
28-- @param file string: pathname to test
29-- @return boolean: true if it is a directory, false otherwise.
30function is_dir(file)
31 assert(file)
32 return fs.execute("chdir /D " .. fs.Q(file) .. " 2>NUL 1>NUL")
33end
34
35--- Run the given command.
36-- The command is executed in the current directory in the dir stack.
37-- @param cmd string: No quoting/escaping is applied to the command.
38-- @return boolean: true if command succeeds (status code 0), false
39-- otherwise.
40function execute_string(cmd)
41 if os.execute(command_at(fs.current_dir(), cmd)) == 0 then
42 return true
43 else
44 return false
45 end
46end
47
48--- Test is pathname is a regular file.
49-- @param file string: pathname to test
50-- @return boolean: true if it is a regular file, false otherwise.
51function is_dir(file)
52 assert(file)
53 return fs.execute("test -d" .. fs.Q(file) .. " 2>NUL 1>NUL")
54end
55
56--- Create a directory if it does not already exist.
57-- If any of the higher levels in the path name does not exist
58-- too, they are created as well.
59-- @param d string: pathname of directory to create.
60-- @return boolean: true on success, false on failure.
61function make_dir(d)
62 assert(d)
63 fs.execute("mkdir "..fs.Q(d).." 1> NUL 2> NUL")
64 return 1
65end
66
67--- Remove a directory if it is empty.
68-- Does not return errors (for example, if directory is not empty or
69-- if already does not exist)
70-- @param d string: pathname of directory to remove.
71function remove_dir_if_empty(d)
72 assert(d)
73 fs.execute_string("rmdir "..fs.Q(d).." 1> NUL 2> NUL")
74end
75
76--- Copy a file.
77-- @param src string: Pathname of source
78-- @param dest string: Pathname of destination
79-- @return boolean or (boolean, string): true on success, false on failure,
80-- plus an error message.
81function copy(src, dest)
82 assert(src and dest)
83 if dest:match("[/\\]$") then dest = dest:sub(1, -2) end
84 if fs.execute("cp", src, dest) then
85 return true
86 else
87 return false, "Failed copying "..src.." to "..dest
88 end
89end
90
91--- Recursively copy the contents of a directory.
92-- @param src string: Pathname of source
93-- @param dest string: Pathname of destination
94-- @return boolean or (boolean, string): true on success, false on failure,
95-- plus an error message.
96function copy_contents(src, dest)
97 assert(src and dest)
98 if fs.execute_string("cp -a "..src.."\\*.* "..fs.Q(dest).." 1> NUL 2> NUL") then
99 return true
100 else
101 return false, "Failed copying "..src.." to "..dest
102 end
103end
104
105--- Delete a file or a directory and all its contents.
106-- For safety, this only accepts absolute paths.
107-- @param arg string: Pathname of source
108-- @return boolean: true on success, false on failure.
109function delete(arg)
110 assert(arg)
111 assert(arg:match("^[\a-zA-Z]?:?[\\/]"))
112 fs.execute("chmod a+rw -R ", arg)
113 return fs.execute_string("rm -rf " .. fs.Q(arg) .. " 1> NUL 2> NUL")
114end
115
116--- List the contents of a directory.
117-- @param at string or nil: directory to list (will be the current
118-- directory if none is given).
119-- @return table: an array of strings with the filenames representing
120-- the contents of a directory.
121function list_dir(at)
122 assert(type(at) == "string" or not at)
123 if not at then
124 at = fs.current_dir()
125 end
126 if not fs.is_dir(at) then
127 return {}
128 end
129 local result = {}
130 local pipe = io.popen(command_at(at, "ls"))
131 for file in pipe:lines() do
132 table.insert(result, file)
133 end
134 pipe:close()
135
136 return result
137end
138
139--- Recursively scan the contents of a directory.
140-- @param at string or nil: directory to scan (will be the current
141-- directory if none is given).
142-- @return table: an array of strings with the filenames representing
143-- the contents of a directory. Paths are returned with forward slashes.
144function find(at)
145 assert(type(at) == "string" or not at)
146 if not at then
147 at = fs.current_dir()
148 end
149 if not fs.is_dir(at) then
150 return {}
151 end
152 local result = {}
153 local pipe = io.popen(command_at(at, "find 2> NUL"))
154 for file in pipe:lines() do
155 -- Windows find is a bit different
156 if file:sub(1,2)==".\\" then file=file:sub(3) end
157 if file ~= "." then
158 table.insert(result, (file:gsub("\\", "/")))
159 end
160 end
161 return result
162end
163
164--- Download a remote file.
165-- @param url string: URL to be fetched.
166-- @param filename string or nil: this function attempts to detect the
167-- resulting local filename of the remote file as the basename of the URL;
168-- if that is not correct (due to a redirection, for example), the local
169-- filename can be given explicitly as this second argument.
170-- @return boolean: true on success, false on failure.
171function download(url, filename)
172 assert(type(url) == "string")
173 assert(type(filename) == "string" or not filename)
174 local wget_cmd = "wget --user-agent="..cfg.user_agent.." --quiet --continue "
175
176 if filename then
177 return fs.execute(wget_cmd.." --output-document ", filename, url)
178 else
179 return fs.execute(wget_cmd, url)
180 end
181end
182
183--- Uncompress gzip file.
184-- @param archive string: Filename of archive.
185-- @return boolean : success status
186local function gunzip(archive)
187 local cmd = fs.execute("gunzip -h 1>NUL 2>NUL") and 'gunzip' or
188 fs.execute("gzip -h 1>NUL 2>NUL") and 'gzip -d'
189 local ok = fs.execute(cmd, archive)
190 return ok
191end
192
193--- Unpack an archive.
194-- Extract the contents of an archive, detecting its format by
195-- filename extension.
196-- @param archive string: Filename of archive.
197-- @return boolean or (boolean, string): true on success, false and an error message on failure.
198function unpack_archive(archive)
199 assert(type(archive) == "string")
200
201 local ok
202 if archive:match("%.tar%.gz$") then
203 ok = gunzip(archive)
204 if ok then
205 ok = fs.execute("tar -xf ", strip_extension(archive))
206 end
207 elseif archive:match("%.tgz$") then
208 ok = gunzip(archive)
209 if ok then
210 ok = fs.execute("tar -xf ", strip_extension(archive)..".tar")
211 end
212 elseif archive:match("%.tar%.bz2$") then
213 ok = fs.execute("bunzip2 ", archive)
214 if ok then
215 ok = fs.execute("tar -xf ", strip_extension(archive))
216 end
217 elseif archive:match("%.zip$") then
218 ok = fs.execute("unzip ", archive)
219 elseif archive:match("%.lua$") or archive:match("%.c$") then
220 -- Ignore .lua and .c files; they don't need to be extracted.
221 return true
222 else
223 local ext = archive:match(".*(%..*)")
224 return false, "Unrecognized filename extension "..(ext or "")
225 end
226 if not ok then
227 return false, "Failed extracting "..archive
228 end
229 return true
230end