2 * Copyright (C) 2009-2010 Red Hat Inc.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
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.
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
19 (* ArchLinux support. *)
24 open Febootstrap_package_handlers
25 open Febootstrap_utils
26 open Febootstrap_cmdline
28 (* Create a temporary directory for use by all the functions in this file. *)
29 let tmpdir = tmpdir ()
31 let pacman_detect () =
32 file_exists "/etc/arch-release" &&
35 let pacman_resolve_dependencies_and_download names =
37 sprintf "(for p in %s; do pactree -u $p; done) | awk '{print $1}' | sort -u"
38 (String.concat " " (List.map Filename.quote names)) in
39 let pkgs = run_command_get_lines cmd in
41 (* Exclude packages matching [--exclude] regexps on the command line. *)
45 not (List.exists (fun re -> Str.string_match re name 0) excludes)
48 (* Download the packages. I could use wget `pacman -Sp`, but this
49 * narrows the pacman -Sy window
54 sprintf "umask 0000; cd %s && mkdir -p var/lib/pacman && fakeroot pacman -Syw --noconfirm --cachedir=$(pwd) --root=$(pwd) %s"
55 (Filename.quote tmpdir)
57 if Sys.command cmd <> 0 then (
58 (* The package is not in the main repos, check the aur *)
60 sprintf "umask 0000; cd %s && wget http://aur.archlinux.org/packages/%s/%s.tar.gz && tar xf %s.tar.gz && cd %s && makepkg && mv %s-*.pkg.tar.xz %s"
61 (Filename.quote tmpdir)
67 (Filename.quote tmpdir) in
72 List.sort compare pkgs
74 let pacman_list_files ?(use_installed=false) pkg =
76 failwith "pacman driver doesn't support --use-installed";
78 debug "unpacking %s ..." pkg;
80 (* We actually need to extract the file in order to get the
81 * information about modes etc.
83 let pkgdir = tmpdir // pkg ^ ".d" in
86 sprintf "ls -1 %s/%s-*.pkg.* | awk '/\\/%s-[^/-]*-[^/-]*-[^/-]*$/ { print $0 }'"
88 let pkgfile = List.hd (run_command_get_lines cmd) in
89 let cmd = sprintf "umask 0000; fakeroot tar -xf %s -C %s"
90 (Filename.quote pkgfile) (Filename.quote pkgdir) in
93 let cmd = sprintf "cd %s && find ." pkgdir in
94 let lines = run_command_get_lines cmd in
96 let files = List.map (
98 assert (path.[0] = '.');
101 if path = "." then "/"
102 else String.sub path 1 (String.length path - 1) in
104 (* Find out what it is and get the canonical filename. *)
105 let statbuf = lstat (pkgdir // path) in
106 let is_dir = statbuf.st_kind = S_DIR in
108 (* No per-file metadata like in RPM, but we can synthesize it
111 let config = statbuf.st_kind = S_REG && string_prefix "/etc/" path in
113 let mode = statbuf.st_perm in
115 (path, { ft_dir = is_dir; ft_config = config; ft_mode = mode;
116 ft_ghost = false; ft_size = statbuf.st_size })
121 (* Easy because we already unpacked the archive above. *)
122 let pacman_get_file_from_package ?(use_installed=false) pkg file =
123 if use_installed then
124 failwith "pacman driver doesn't support --use-installed";
126 tmpdir // pkg ^ ".d" // file
130 ph_detect = pacman_detect;
131 ph_resolve_dependencies_and_download =
132 pacman_resolve_dependencies_and_download;
133 ph_list_files = pacman_list_files;
134 ph_get_file_from_package = pacman_get_file_from_package;
136 register_package_handler "pacman" ph