Add query for existence of package
[hcoop/domtool2.git] / src / plugins / apt.sml
1 (* HCoop Domtool (http://hcoop.sourceforge.net/)
2 * Copyright (c) 2006-2007, Adam Chlipala
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 *)
18
19 (* APT package database querying *)
20
21 structure Apt :> APT = struct
22
23 fun validName s = CharVector.all (fn ch => Char.isAlphaNum ch orelse ch = #"_" orelse ch = #"-" orelse ch = #".") s
24 andalso (size s > 0 andalso String.sub (s, 0) <> #"-")
25
26 (* Copyed from the portal, doesn't exactly go out this in the most
27 direct way, or does it? *)
28
29 fun exists name =
30 validName name andalso let
31 val proc = Unix.execute ("/usr/bin/apt-cache", ["show", name])
32 val inf = Unix.textInstreamOf proc
33
34 val _ = TextIO.inputLine inf (* in every let* lies an imperative program in disguise *)
35
36 fun loop _ =
37 case TextIO.inputLine inf of
38 NONE => false
39 | SOME line =>
40 if size line >= 9 andalso String.substring (line, 0, 9) = "Section: " then
41 true
42 else if size line >= 13 andalso String.substring (line, 0, 13) = "Description: " then
43 false
44 else
45 loop ()
46 in
47 loop ()
48 before ignore (Unix.reap proc)
49 end
50
51 fun installed name =
52 validName name
53 andalso let
54 val proc = Unix.execute ("/usr/bin/apt-cache", ["policy", name])
55 val inf = Unix.textInstreamOf proc
56
57 val _ = TextIO.inputLine inf
58 in
59 (case TextIO.inputLine inf of
60 NONE => false
61 | SOME line =>
62 case String.tokens Char.isSpace line of
63 [_, "(none)"] => false
64 | [_, _] => true
65 | _ => false)
66 before ignore (Unix.reap proc)
67 end
68
69 end