From 06563409e6f2b1cca7bc1b27e31efd07a7569da8 Mon Sep 17 00:00:00 2001 From: Philip McGrath Date: Thu, 14 Apr 2022 22:41:04 -0400 Subject: [PATCH] minimal support for offline builds Normally, Elm performs HTTP requests before building to obtain or update its list of all registed packages and their versions. This is problematic in the Guix build environment. This patch causes Elm to check if the `GUIX_ELM_OFFLINE_REGISTRY_FILE` is set and, if so, to use the contents of the file it specifies as though it were the response from https://package.elm-lang.org/all-packages. This patch does not attempt to add more general support for offline builds. In particular, it does not attempt to support incremental updates to the package registry cache file. See also discussion at https://discourse.elm-lang.org/t/private-package-tool-spec/6779/25. --- builder/src/Deps/Registry.hs | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/builder/src/Deps/Registry.hs b/builder/src/Deps/Registry.hs index 8d7def98..70cf3622 100644 --- a/builder/src/Deps/Registry.hs +++ b/builder/src/Deps/Registry.hs @@ -18,6 +18,8 @@ import Control.Monad (liftM2) import Data.Binary (Binary, get, put) import qualified Data.List as List import qualified Data.Map.Strict as Map +import System.Environment as Env +import qualified Data.ByteString as BS import qualified Deps.Website as Website import qualified Elm.Package as Pkg @@ -190,13 +192,28 @@ getVersions' name (Registry _ versions) = post :: Http.Manager -> String -> D.Decoder x a -> (a -> IO b) -> IO (Either Exit.RegistryProblem b) post manager path decoder callback = let - url = Website.route path [] - in - Http.post manager url [] Exit.RP_Http $ - \body -> + mkBodyCallback url body = case D.fromByteString decoder body of Right a -> Right <$> callback a Left _ -> return $ Left $ Exit.RP_Data url body + postOnline url cb = + Http.post manager url [] Exit.RP_Http cb + performPost f url = + f url (mkBodyCallback url) + in + do + maybeFile <- Env.lookupEnv "GUIX_ELM_OFFLINE_REGISTRY_FILE" + case (path, maybeFile) of + ( "/all-packages", Just file ) -> + performPost postOffline file + ( _, _ ) -> + -- don't know how to handle other endpoints yet + performPost postOnline (Website.route path []) + +postOffline :: String -> (BS.ByteString -> IO a) -> IO a +postOffline file callback = do + body <- BS.readFile file + callback body -- 2.32.0 [Guix requires zlib. See http://www.zlib.net/.])]) dnl Look for libbz2, an optional dependency. AC_CHECK_LIB([bz2], [BZ2_bzWriteOpen], [HAVE_LIBBZ2=yes], [HAVE_LIBBZ2=no]) if test "x$HAVE_LIBBZ2" = xyes; then AC_CHECK_HEADERS([bzlib.h]) HAVE_LIBBZ2="$ac_cv_header_bzlib_h" fi dnl Look for SQLite, a required dependency. PKG_CHECK_MODULES([SQLITE3], [sqlite3 >= 3.6.19]) AC_DEFINE_UNQUOTED([SYSTEM], ["$guix_system"], [Guix host system type--i.e., platform and OS kernel tuple.]) case "$LIBGCRYPT_PREFIX" in no) LIBGCRYPT_CPPFLAGS="" ;; *) LIBGCRYPT_CPPFLAGS="-I$LIBGCRYPT_PREFIX/include" ;; esac case "$LIBGCRYPT_LIBDIR" in no | "") ;; *) LIBGCRYPT_LDFLAGS="-L$LIBGCRYPT_LIBDIR" ;; esac LIBGCRYPT_LIBS="-lgcrypt" AC_SUBST([LIBGCRYPT_CPPFLAGS]) AC_SUBST([LIBGCRYPT_LDFLAGS]) AC_SUBST([LIBGCRYPT_LIBS]) save_CPPFLAGS="$CPPFLAGS" save_LDFLAGS="$LDFLAGS" save_LIBS="$LIBS" CPPFLAGS="$CPPFLAGS $LIBGCRYPT_CPPFLAGS" LDFLAGS="$LDFLAGS $LIBGCRYPT_LDFLAGS" LIBS="$LIBS $LIBGCRYPT_LIBS" have_gcrypt=yes AC_CHECK_LIB([gcrypt], [gcry_md_open], [:], [have_gcrypt=no]) AC_CHECK_HEADER([gcrypt.h], [:], [have_gcrypt=no]) if test "x$have_gcrypt" != "xyes"; then AC_MSG_ERROR([GNU libgcrypt not found; please install it.]) fi CPPFLAGS="$save_CPPFLAGS" LDFLAGS="$save_LDFLAGS" LIBS="$save_LIBS" dnl Chroot support. AC_CHECK_FUNCS([chroot unshare]) AC_CHECK_HEADERS([sched.h sys/param.h sys/mount.h sys/syscall.h]) if test "x$ac_cv_func_chroot" != "xyes"; then AC_MSG_ERROR(['chroot' function missing, bailing out]) fi dnl lutimes and lchown: used when canonicalizing store items. dnl posix_fallocate: used when extracting archives. dnl vfork: to speed up spawning of helper programs. dnl `--> now disabled because of unpredictable behavior: dnl see <http://lists.gnu.org/archive/html/guix-devel/2014-05/msg00036.html> dnl and Nix commit f794465c (Nov. 2012). dnl sched_setaffinity: to improve RPC locality. dnl statvfs: to detect disk-full conditions. dnl strsignal: for error reporting. dnl statx: fine-grain 'stat' call, new in glibc 2.28. AC_CHECK_FUNCS([lutimes lchown posix_fallocate sched_setaffinity \ statvfs nanosleep strsignal statx]) dnl Check for <locale>. AC_LANG_PUSH(C++) AC_CHECK_HEADERS([locale]) AC_LANG_POP(C++) dnl Check whether we have the `personality' syscall, which allows us dnl to do i686-linux builds on x86_64-linux machines. AC_CHECK_HEADERS([sys/personality.h]) dnl Determine the appropriate default list of substitute URLs (GnuTLS dnl is required so we can default to 'https'.) GUIX_SUBSTITUTE_URLS="https://bordeaux.guix.gnu.org https://ci.guix.gnu.org" AC_MSG_CHECKING([for default substitute URLs]) AC_MSG_RESULT([$GUIX_SUBSTITUTE_URLS]) AC_SUBST([GUIX_SUBSTITUTE_URLS]) AC_DEFINE_UNQUOTED([GUIX_SUBSTITUTE_URLS], ["$GUIX_SUBSTITUTE_URLS"], [Default list of substitute URLs used by 'guix-daemon'.]) dnl Check for Guile-SSH, which is required by 'guix offload'. GUIX_CHECK_GUILE_SSH case "x$guix_cv_have_recent_guile_ssh" in xyes) guix_build_daemon_offload="yes" AC_DEFINE([HAVE_DAEMON_OFFLOAD_HOOK], [1], [Define if the daemon's 'offload' build hook is being built (requires Guile-SSH).]) ;; *) guix_build_daemon_offload="no" ;; esac dnl Temporary directory used to store the daemon's data. GUIX_TEST_ROOT_DIRECTORY GUIX_TEST_ROOT="$ac_cv_guix_test_root" AC_SUBST([GUIX_TEST_ROOT]) GUIX_CHECK_LOCALSTATEDIR fi AM_CONDITIONAL([HAVE_LIBBZ2], [test "x$HAVE_LIBBZ2" = "xyes"]) AM_CONDITIONAL([BUILD_DAEMON], [test "x$guix_build_daemon" = "xyes"]) AM_CONDITIONAL([BUILD_DAEMON_OFFLOAD], \ [test "x$guix_build_daemon" = "xyes" \ && test "x$guix_build_daemon_offload" = "xyes"])