Add support for Arch Linux (pacman package manager).
authorThomas S Hatch <thatch45@gmail.com>
Mon, 6 Dec 2010 15:26:43 +0000 (15:26 +0000)
committerRichard W.M. Jones <rjones@redhat.com>
Mon, 6 Dec 2010 15:26:51 +0000 (15:26 +0000)
.depend
Makefile.am
config.ml.in
configure.ac
febootstrap_pacman.ml [new file with mode: 0644]

diff --git a/.depend b/.depend
index 9f90bab..202d8c6 100644 (file)
--- a/.depend
+++ b/.depend
@@ -19,6 +19,10 @@ febootstrap_debian.cmo: febootstrap_utils.cmi \
     febootstrap_package_handlers.cmi febootstrap_cmdline.cmi config.cmo 
 febootstrap_debian.cmx: febootstrap_utils.cmx \
     febootstrap_package_handlers.cmx febootstrap_cmdline.cmx config.cmx 
+febootstrap_pacman.cmo: febootstrap_utils.cmi \
+    febootstrap_package_handlers.cmi febootstrap_cmdline.cmi config.cmo 
+febootstrap_pacman.cmx: febootstrap_utils.cmx \
+    febootstrap_package_handlers.cmx febootstrap_cmdline.cmx config.cmx 
 febootstrap.cmo: febootstrap_utils.cmi febootstrap_package_handlers.cmi \
     febootstrap_cmdline.cmi config.cmo 
 febootstrap.cmx: febootstrap_utils.cmx febootstrap_package_handlers.cmx \
index 3dcbe1f..d04412c 100644 (file)
@@ -32,6 +32,7 @@ SOURCES = \
        febootstrap_package_handlers.ml \
        febootstrap_yum_rpm.ml \
        febootstrap_debian.ml \
+       febootstrap_pacman.ml \
        febootstrap.ml
 
 CLEANFILES = *~ *.cmi *.cmo *.cmx *.o febootstrap
index ebda655..a8c008a 100644 (file)
@@ -24,4 +24,5 @@ let rpm = "@RPM@"
 let yumdownloader = "@YUMDOWNLOADER@"
 let aptitude = "@APTITUDE@"
 let dpkg = "@DPKG@"
+let pacman = "@PACMAN@"
 let host_cpu = "@host_cpu@"
index 21dd340..aa28498 100644 (file)
@@ -64,6 +64,9 @@ dnl For Debian handler.
 AC_CHECK_PROG(APTITUDE,[aptitude],[aptitude],[no])
 AC_CHECK_PROG(DPKG,[dpkg],[dpkg],[no])
 
+dnl For ArchLinux handler.
+AC_CHECK_PROG(PACMAN,[pacman],[pacman],[no])
+
 dnl Required programs, libraries.
 AC_PATH_PROG([INSMODSTATIC],[insmod.static],[no])
 if test "x$INSMODSTATIC" = "xno" ; then
diff --git a/febootstrap_pacman.ml b/febootstrap_pacman.ml
new file mode 100644 (file)
index 0000000..bc2a887
--- /dev/null
@@ -0,0 +1,134 @@
+(* febootstrap 3
+ * Copyright (C) 2009-2010 Red Hat Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *)
+
+(* ArchLinux support. *)
+
+open Unix
+open Printf
+
+open Febootstrap_package_handlers
+open Febootstrap_utils
+open Febootstrap_cmdline
+
+(* Create a temporary directory for use by all the functions in this file. *)
+let tmpdir = tmpdir ()
+
+let pacman_detect () =
+  file_exists "/etc/arch-release" &&
+    Config.pacman <> "no"
+
+let pacman_resolve_dependencies_and_download names =
+  let cmd =
+    sprintf "pactree -u %s | sort -u"
+      (String.concat " " (List.map Filename.quote names)) in
+  let pkgs = run_command_get_lines cmd in
+
+  (* Exclude packages matching [--exclude] regexps on the command line. *)
+  let pkgs =
+    List.filter (
+      fun name ->
+        not (List.exists (fun re -> Str.string_match re name 0) excludes)
+    ) pkgs in
+
+  (* Download the packages. I could use wget `pacman -Sp`, but this
+   * narrows the pacman -Sy window
+   *)
+  let cmd =
+    sprintf "cd %s && mkdir -p var/lib/pacman && fakeroot pacman -Syw --noconfirm --cachedir=$(pwd) --root=$(pwd) %s"
+      (Filename.quote tmpdir)
+      (String.concat " " (List.map Filename.quote pkgs)) in
+  run_command cmd;
+
+  (* Find out what pacman downloaded. *)
+  (*let files = Sys.readdir tmpdir in
+
+  let pkgs = List.map (
+    fun pkg ->
+      (* Look for 'pkg*.pkg.tar.xz' in the list of files. *)
+      let pre = pkg in
+      let r = ref "" in
+      try
+       for i = 0 to Array.length files - 1 do
+         if string_prefix pre files.(i) then (
+           r := files.(i);
+           files.(i) <- "";
+           raise Exit
+         )
+       done;
+       eprintf "febootstrap: pacman: error: no file was downloaded corresponding to package %s\n" pkg;
+       exit 1
+      with
+         Exit -> !r
+  ) pkgs in *)
+
+  List.sort compare pkgs
+
+let pacman_list_files pkg =
+  debug "unpacking %s ..." pkg;
+
+  (* We actually need to extract the file in order to get the
+   * information about modes etc.
+   *)
+  let pkgdir = tmpdir // pkg ^ ".d" in
+  mkdir pkgdir 0o755;
+  let cmd =
+    sprintf "tar -xf %s-* -C %s"
+      (tmpdir // pkg ) pkgdir in
+  run_command cmd;
+
+  let cmd = sprintf "cd %s && find ." pkgdir in
+  let lines = run_command_get_lines cmd in
+
+  let files = List.map (
+    fun path ->
+      assert (path.[0] = '.');
+      (* No leading '.' *)
+      let path =
+       if path = "." then "/"
+       else String.sub path 1 (String.length path - 1) in
+
+      (* Find out what it is and get the canonical filename. *)
+      let statbuf = lstat (pkgdir // path) in
+      let is_dir = statbuf.st_kind = S_DIR in
+
+      (* No per-file metadata like in RPM, but we can synthesize it
+       * from the path.
+       *)
+      let config = statbuf.st_kind = S_REG && string_prefix path "/etc/" in
+
+      let mode = statbuf.st_perm in
+
+      (path, { ft_dir = is_dir; ft_config = config; ft_mode = mode;
+              ft_ghost = false })
+  ) lines in
+
+  files
+
+(* Easy because we already unpacked the archive above. *)
+let pacman_get_file_from_package pkg file =
+  tmpdir // pkg ^ ".d" // file
+
+let () =
+  let ph = {
+    ph_detect = pacman_detect;
+    ph_resolve_dependencies_and_download =
+      pacman_resolve_dependencies_and_download;
+    ph_list_files = pacman_list_files;
+    ph_get_file_from_package = pacman_get_file_from_package;
+  } in
+  register_package_handler "pacman" ph