Package: qemubuilder
Version: 0.78
Severity: wishlist
Tags: patch

Hi,

it would be awesome if qemubuilder supported running hooks during
build, so that you are able to customize it.
I implemented copying files from a directory (HOOKDIR=) to qemu
and run some of pbuilder's supported hook types at the correct
time.

Kind regards,
  Reiner
From 095eeb43c44f62eb369fe9e3acb97dad28c60235 Mon Sep 17 00:00:00 2001
From: Reiner Herrmann <[email protected]>
Date: Sat, 2 Apr 2016 14:25:03 +0200
Subject: [PATCH] qemubuilder: add support for hooks

Copy files from the directory configured in the HOOKDIR
setting to the hook dir in qemu (/etc/pbuilder/hooks).
The hooks are then run at the appropriate times, depending
on the first letter of the filename, comparable to the
pbuilder hooks.

Hooks of the following types are currently supported:
A, D, E, F, G
---
 parameter.c   |  5 +++++
 parameter.h   |  1 +
 qemubuilder.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++--------
 3 files changed, 67 insertions(+), 9 deletions(-)

diff --git a/parameter.c b/parameter.c
index 8c015a6..8a41660 100644
--- a/parameter.c
+++ b/parameter.c
@@ -190,6 +190,10 @@ int load_config_file(const char* config, pbuilderconfig* pc)
 	    {
 	      pc->http_proxy=strdup_strip_quote(delim);
 	    }
+	  else if (!strcmp(buf, "HOOKDIR"))
+	    {
+	      pc->hookdir=strdup_strip_quote(delim);
+	    }
 	}
     }
 
@@ -237,6 +241,7 @@ int cpbuilder_dumpconfig(pbuilderconfig* pc)
   DUMPSTR(debbuildopts);
   DUMPINT(binary_arch);
   DUMPSTR(http_proxy);
+  DUMPSTR(hookdir);
   DUMPSTRARRAY(inputfile);
   DUMPSTRARRAY(outputfile);
 
diff --git a/parameter.h b/parameter.h
index 9ef23a7..7f0aa9b 100644
--- a/parameter.h
+++ b/parameter.h
@@ -41,6 +41,7 @@ typedef struct pbuilderconfig
   char* debbuildopts;
   int binary_arch;
   char* http_proxy;
+  char* hookdir;
 
   /* files to be copied into the chroot,
      and copied out of the chroot */
diff --git a/qemubuilder.c b/qemubuilder.c
index 502a48a..4f8fb65 100755
--- a/qemubuilder.c
+++ b/qemubuilder.c
@@ -27,6 +27,8 @@
 #include <sys/socket.h>
 #include <string.h>
 #include <unistd.h>
+#include <errno.h>
+#include <dirent.h>
 #include <getopt.h>
 #include <stdarg.h>
 #include <assert.h>
@@ -38,6 +40,9 @@
 #include "qemuarch.h"
 #include "file.h"
 
+#define HOOKDIR "/etc/pbuilder/hooks"
+#define execute_hooks(type) "for hook in $(ls "HOOKDIR" | grep ^" type "); do echo \"  -> Running hook $hook\"; BUILDDIR=/tmp/buildd "HOOKDIR"/$hook; done\n"
+
 /*
  * example exit codes:
  *
@@ -174,13 +179,47 @@ static int copy_file_contents_through_temp(FILE* f,
 
   fprintf(f,
 	  "echo \"I: copying %s/%s from temporary location\"\n"
+	  "mkdir -p %s\n"
 	  "cp $PBUILDER_MOUNTPOINT/%s %s/%s || echo \"E: Copy failed\"\n",
 	  targetdir, file_basename,
+	  targetdir,
 	  file_basename,
 	  targetdir, file_basename);
   return ret;
 }
 
+static void copy_hooks_dir(FILE *f, const char *hooks_dir, const char *tmp)
+{
+  struct dirent *dirp;
+  DIR *hd = opendir(hooks_dir);
+
+  if (hd == NULL)
+    {
+      printf("can't copy hooks from '%s': %s\n", hooks_dir, strerror(errno));
+      return;
+    }
+
+  while((dirp = readdir(hd)) != NULL)
+    {
+      struct stat st;
+      char *src = NULL;
+
+      asprintf(&src, "%s/%s", hooks_dir, dirp->d_name);
+      if (stat(src, &st) == -1)
+        {
+          printf("can't stat file '%s': %s\n", src, strerror(errno));
+          continue;
+        }
+
+      if ((st.st_mode & S_IFMT) != S_IFREG)
+        continue;
+
+      copy_file_contents_through_temp(f, src, tmp, HOOKDIR);
+      fprintf(f, "chmod 0755 %s/%s\n", HOOKDIR, dirp->d_name);
+    }
+  closedir(hd);
+}
+
 /**
    run qemu until exit signal is received from within QEMU via serial
    console.
@@ -479,9 +518,10 @@ static int run_second_stage_script
 	  "export IFNAME=`/sbin/ifconfig -a | grep eth | head -n1 | awk '{print $1}'`\n"
 	  "dhclient $IFNAME\n"
 	  "mkdir -p /tmp/buildd\n"
+	  "mkdir -p "HOOKDIR"\n"
 	  "$PBUILDER_MOUNTPOINT/run-copyfiles\n"
 	  "hostname pbuilder-$(cat /etc/hostname)\n"
-	  //TODO: run G hook
+	  execute_hooks("G")
 	  "%s\n"
 	  //TODO: I can mount /var/cache/apt/archives from some scratch space to not need this:
 	  "apt-get clean || true\n"
@@ -500,10 +540,14 @@ static int run_second_stage_script
     {
       copy_file_contents_through_temp(f, pc->inputfile[i], pc->buildplace, "/tmp/buildd");
     }
+  /* copy hooks */
+  if (pc->hookdir != NULL)
+    {
+      copy_hooks_dir(f, pc->hookdir, pc->buildplace);
+    }
   fclose(f);
 
   /* do I not need to copy /etc/pbuilderrc, and ~/.pbuilderrc to inside chroot? */
-  /* TODO: hooks probably need copying here. */
   /* TODO: recover aptcache */
 
   if(hostcommand1)
@@ -778,11 +822,12 @@ int cpbuilder_create(const struct pbuilderconfig* pc)
 	  "mkdir /dev/pts\n"
 	  "mount -n devpts /dev/pts -t devpts\n"
 	  "dhclient eth0\n"
+	  "mkdir -p "HOOKDIR"\n"
 	  "$PBUILDER_MOUNTPOINT/run-copyfiles\n"
 	  "hostname pbuilder-$(cat /etc/hostname)\n"
 	  //TODO: installaptlines
 	  "echo '%s' > /etc/apt/sources.list.d/other.list\n"
-	  //TODO: run G hook
+	  execute_hooks("G")
 	  "apt-get update || exit_from_qemu 1\n"
 	  //TODO: "dpkg --purge $REMOVEPACKAGES\n"
 	  //recover aptcache
@@ -791,7 +836,7 @@ int cpbuilder_create(const struct pbuilderconfig* pc)
 	  //TODO: EXTRAPACKAGES handling
 	  //save aptcache
 	  //optionally autoclean aptcache
-	  //run E hook
+	  execute_hooks("E")
 	  //TODO: I can mount /var/cache/apt/archives from some scratch space to not need this:
 	  "apt-get clean || true\n"
 	  "exit_from_qemu $RET\n"
@@ -811,10 +856,14 @@ int cpbuilder_create(const struct pbuilderconfig* pc)
   f = create_script(pc->buildplace, "run-copyfiles");
   copy_file_contents_through_temp(f, "/etc/hosts", pc->buildplace, "/etc");
   copy_file_contents_through_temp(f, "/etc/hostname", pc->buildplace, "/etc");
+  /* copy hooks */
+  if (pc->hookdir != NULL)
+    {
+      copy_hooks_dir(f, pc->hookdir, pc->buildplace);
+    }
   fclose(f);
 
   /* do I not need to copy /etc/pbuilderrc, and ~/.pbuilderrc to inside chroot? */
-  /* TODO: hooks probably need copying here. */
   /* TODO: recover aptcache */
 
   loop_umount(pc->buildplace);
@@ -864,11 +913,11 @@ int cpbuilder_build(const struct pbuilderconfig* pc, const char* dscfile)
   hoststr=copy_dscfile(dscfile, pc->buildplace);
 
   asprintf(&commandline,
-	   /* TODO: executehooks D: */
+	   execute_hooks("D")
 	   "/usr/lib/pbuilder/pbuilder-satisfydepends --control $PBUILDER_MOUNTPOINT/*.dsc --internal-chrootexec 'chroot . ' %s \n"
 	   "cd $PBUILDER_MOUNTPOINT; /usr/bin/dpkg-source -x $(basename %s) \n"
 	   "echo ' -> Building the package'\n"
-	   /* TODO: executehooks A: */
+	   execute_hooks("A")
 	   "cd $PBUILDER_MOUNTPOINT/*-*/; dpkg-buildpackage -us -uc %s\n",
 	   buildopt,
 	   dscfile,
@@ -897,6 +946,7 @@ int cpbuilder_build(const struct pbuilderconfig* pc, const char* dscfile)
 int cpbuilder_login(const struct pbuilderconfig* pc)
 {
   return run_second_stage_script(pc->save_after_login,
+				 execute_hooks("F")
 				 "bash",
 				 pc,
 				 NULL,
@@ -916,7 +966,9 @@ int cpbuilder_execute(const struct pbuilderconfig* pc, char** av)
 
   asprintf(&hostcommand, "cp %s %s/runscript\n", av[0], pc->buildplace);
   /* TODO: add options too */
-  asprintf(&runcommandline, "sh $PBUILDER_MOUNTPOINT/runscript");
+  asprintf(&runcommandline,
+	  execute_hooks("F")
+	  "sh $PBUILDER_MOUNTPOINT/runscript");
   ret=run_second_stage_script(pc->save_after_login, runcommandline, pc,
 			      hostcommand, NULL);
   free(hostcommand);
@@ -944,7 +996,7 @@ int cpbuilder_update(const struct pbuilderconfig* pc)
      "apt-get install --force-yes -y build-essential dpkg-dev apt aptitude pbuilder\n"
      //TODO: EXTRAPACKAGES handling
      //optionally autoclean aptcache
-     //run E hook
+     execute_hooks("E")
      , pc,
      NULL, NULL);
 }
-- 
2.8.0.rc3

Attachment: signature.asc
Description: PGP signature

Reply via email to