packages feed

nix-thunk 0.4.0.0 → 0.5.0.0

raw patch · 6 files changed

+109/−45 lines, 6 filesdep +processdep +template-haskelldep ~cli-extrasdep ~cli-git

Dependencies added: process, template-haskell

Dependency ranges changed: cli-extras, cli-git

Files

CHANGELOG.md view
@@ -1,8 +1,14 @@ # Revision history for nix-thunk +## 0.5.0.0++* Fix a critical bug where v6 thunks can not be used to fetch non-GitHub repositories. Please update all your thunks to use the new v7 thunk spec.+  Updating your thunk can be done by running `nix-thunk unpack $path; nix-thunk pack $path`.+* Building a functional `nix-thunk` _must_ be done using the included Nix derivation.+ ## 0.4.0.0 -* The default thunk specification ("v6") now uses a pinned version of nixpkgsk, rather than the magic `<nixpkgs>`, for fetching thunks. This ensures that thunks can be fetched even in an environment where `NIX_PATH` is unset.+* The default thunk specification ("v6") now uses a pinned version of nixpkgs, rather than the magic `<nixpkgs>`, for fetching thunks. This ensures that thunks can be fetched even in an environment where `NIX_PATH` is unset.  ## 0.3.0.0 
README.md view
@@ -21,6 +21,8 @@ nix-env -f https://github.com/obsidiansystems/nix-thunk/archive/master.tar.gz -iA command ``` +**WARNING**: It is _not_ possible to compile `nix-thunk` without Nix. To ensure that packed thunks are buildable even in environments where diamond paths are unavailable (specifically `<nixpkgs>`), `nix-thunk` _must_ be built with knowledge of a known-good nixpkgs, _and_ for `nix-thunk` to be able to manipulate these thunks, it must _always_ be the same version of nixpkgs.+ ## Command Usage  ### Create a dependency
nix-thunk.cabal view
@@ -1,6 +1,6 @@ cabal-version:      >=1.10 name:               nix-thunk-version:            0.4.0.0+version:            0.5.0.0 license:            BSD3 license-file:       LICENSE copyright:          Obsidian Systems LLC 2020-2022@@ -34,8 +34,8 @@     , aeson-pretty          >=0.8.7    && <0.9     , base                  >=4.12.0.0 && <4.15     , bytestring            >=0.10.8.2 && <0.11-    , cli-extras            >=0.1.0.1  && <0.2-    , cli-git               >=0.1.0.1  && <0.2+    , cli-extras            >=0.2.1.0  && <0.3+    , cli-git               >=0.2.0.0  && <0.3     , cli-nix               >=0.1.0.1  && <0.2     , containers            >=0.6.0.1  && <0.7     , cryptonite            >=0.25     && <0.30@@ -61,13 +61,15 @@     , unix                  >=2.7.2.2  && <2.8     , which                 >=0.2      && <0.3     , yaml                  >=0.11.1.2 && <0.12+    , process               >=1.6.0.0  && <1.7+    , template-haskell      >=2.14.0.0 && <2.19  executable nix-thunk   main-is:          src-bin/nix-thunk.hs   default-language: Haskell2010   build-depends:       base                  >=4.12.0.0 && <4.15-    , cli-extras            >=0.1.0.1  && <0.2+    , cli-extras            >=0.2.1.0  && <0.3     , nix-thunk     , optparse-applicative  >=0.14.3.0 && <0.17     , text                  >=1.2.3.1  && <1.3
src-bin/nix-thunk.hs view
@@ -7,6 +7,8 @@ import qualified Data.Text.IO as T import System.Environment import System.Exit+import System.IO+import Data.List import Data.Void  data Args = Args@@ -35,13 +37,25 @@   { prefShowHelpOnEmpty = True   } -main :: IO Void-main = do-  args <- getArgs-  args' <- handleParseResult $ execParserPure parserPrefs argsInfo args-  cliConf <- mkDefaultCliConfig args-  runCli cliConf (runThunkCommand (_args_command args')) >>= \case-    Right () -> exitWith ExitSuccess-    Left e -> do-      T.putStrLn $ prettyNixThunkError e-      exitWith $ ExitFailure 2+main :: IO ()+main =+  do+    args <- getArgs+    args' <- handleParseResult $ execParserPure parserPrefs argsInfo args+    let logLevel = if _args_verbose args' then Debug else Notice+    notInteractive <- not <$> isInteractiveTerm args+    cliConf <- newCliConfig logLevel notInteractive notInteractive (\e -> (prettyNixThunkError e, ExitFailure 1))+    runCli cliConf (runThunkCommand (_args_command args'))+  where+    isInteractiveTerm args = do+      isTerm <- hIsTerminalDevice stdout+      -- Running in bash/fish/zsh completion+      let inShellCompletion = isInfixOf "completion" $ unwords args++      -- Respect the user’s TERM environment variable. Dumb terminals+      -- like Eshell cannot handle lots of control sequences that the+      -- spinner uses.+      termEnv <- lookupEnv "TERM"+      let isDumb = termEnv == Just "dumb"++      return $ isTerm && not inShellCompletion && not isDumb
src/Nix/Thunk.hs view
@@ -30,6 +30,7 @@   , ThunkPackConfig (..)   , ThunkConfig (..)   , updateThunkToLatest+  , updateThunk   , ThunkUpdateConfig (..)   , unpackThunk   , ThunkSpec (..)@@ -102,6 +103,8 @@ import System.IO.Temp import System.Posix.Files import qualified Text.URI as URI+import Language.Haskell.TH (Exp(LitE), Lit(StringL), runIO)+import qualified System.Process as P  -------------------------------------------------------------------------------- -- Hacks@@ -109,7 +112,7 @@  type MonadInfallibleNixThunk m =   ( CliLog m-  , HasCliConfig m+  , HasCliConfig NixThunkError m   , MonadIO m   , MonadMask m   )@@ -126,7 +129,8 @@  prettyNixThunkError :: NixThunkError -> Text prettyNixThunkError = \case-  NixThunkError_ProcessFailure pf -> prettyProcessFailure pf+  NixThunkError_ProcessFailure (ProcessFailure p code) ->+    "Process exited with code " <> T.pack (show code) <> "; " <> reconstructCommand p   NixThunkError_Unstructured msg -> msg  makePrisms ''NixThunkError@@ -248,11 +252,6 @@   , _gitSource_private = _gitHubSource_private s   } -getThunkGitBranch :: ThunkPtr -> Maybe Text-getThunkGitBranch (ThunkPtr _ src) = fmap untagName $ case src of-  ThunkSource_GitHub s -> _gitHubSource_branch s-  ThunkSource_Git s -> _gitSource_branch s- commitNameToRef :: Name Commit -> Ref SHA1 commitNameToRef (N c) = refFromHex $ encodeUtf8 c @@ -300,6 +299,17 @@ attrCacheFileName :: FilePath attrCacheFileName = ".attr-cache" +-- | A path from which our known-good nixpkgs can be fetched.+-- @print-nixpkgs-path@ is a shell script whose only purpose is to print+-- that path. It is generated and included in the build dependencies of+-- nix-thunk by our default.nix.+pinnedNixpkgsPath :: FilePath+pinnedNixpkgsPath =+  $(do+    p <- fmap init . runIO $ P.readCreateProcess (P.shell "print-nixpkgs-path") ""+    pure $ LitE $ StringL $ p+  )+ -- | Specification for how a file in a thunk version works. data ThunkFileSpec   = ThunkFileSpec_Ptr (LBS.ByteString -> Either String ThunkPtr) -- ^ This file specifies 'ThunkPtr' data@@ -520,14 +530,6 @@       liftIO $ createDirectoryIfMissing True $ takeDirectory fullPath       f fullPath -createThunkWithLatest :: MonadNixThunk m => FilePath -> ThunkSource -> m ()-createThunkWithLatest target s = do-  rev <- getLatestRev s-  createThunk target $ Right $ ThunkPtr-    { _thunkPtr_source = s-    , _thunkPtr_rev = rev-    }- updateThunkToLatest :: MonadNixThunk m => ThunkUpdateConfig -> FilePath -> m () updateThunkToLatest (ThunkUpdateConfig mBranch thunkConfig) target = do   withSpinner' ("Updating thunk " <> T.pack target <> " to latest") (pure $ const $ "Thunk " <> T.pack target <> " updated to latest") $ do@@ -562,8 +564,9 @@ -- This tool will only ever produce the newest one when it writes a thunk. gitHubThunkSpecs :: NonEmpty ThunkSpec gitHubThunkSpecs =-  gitHubThunkSpecV6 :|-  [ gitHubThunkSpecV5+  gitHubThunkSpecV7 :|+  [ gitHubThunkSpecV6+  , gitHubThunkSpecV5   , gitHubThunkSpecV4   , gitHubThunkSpecV3   , gitHubThunkSpecV2@@ -638,10 +641,11 @@ in fetch json |] --- | Specification for GitHub thunks which use a specific, pinned--- version of nixpkgs for fetching, rather than using @<nixpkgs>@ from--- @NIX_PATH@. The "v6" specs ensure that thunks can be fetched even--- when @NIX_PATH@ is unset.+-- | See 'gitHubThunkSpecV7'.+--+-- __NOTE__: v6 spec thunks are broken! They import the pinned nixpkgs+-- in an incorrect way. GitHub thunks for public repositories with no+-- submodules will still work, but update as soon as possible. gitHubThunkSpecV6 :: ThunkSpec gitHubThunkSpecV6 = mkThunkSpec "github-v6" "github.json" parseGitHubJsonBytes [here| # DO NOT HAND-EDIT THIS FILE@@ -658,14 +662,30 @@ in fetch json |] +-- | Specification for GitHub thunks which use a specific, pinned+-- version of nixpkgs for fetching, rather than using @<nixpkgs>@ from+-- @NIX_PATH@. The "v7" specs ensure that thunks can be fetched even+-- when @NIX_PATH@ is unset.+gitHubThunkSpecV7 :: ThunkSpec+gitHubThunkSpecV7 = mkThunkSpec "github-v7" "github.json" parseGitHubJsonBytes [i|# DO NOT HAND-EDIT THIS FILE+let fetch = { private ? false, fetchSubmodules ? false, owner, repo, rev, sha256, ... }:+  if !fetchSubmodules && !private then builtins.fetchTarball {+    url = "https://github.com/\${owner}/\${repo}/archive/\${rev}.tar.gz"; inherit sha256;+  } else (import ${pinnedNixpkgsPath} {}).fetchFromGitHub {+    inherit owner repo rev sha256 fetchSubmodules private;+  };+  json = builtins.fromJSON (builtins.readFile ./github.json);+in fetch json|]+ parseGitHubJsonBytes :: LBS.ByteString -> Either String ThunkPtr parseGitHubJsonBytes = parseJsonObject $ parseThunkPtr $ \v ->   ThunkSource_GitHub <$> parseGitHubSource v <|> ThunkSource_Git <$> parseGitSource v  gitThunkSpecs :: NonEmpty ThunkSpec gitThunkSpecs =-  gitThunkSpecV6 :|-  [ gitThunkSpecV5+  gitThunkSpecV7 :|+  [ gitThunkSpecV6+  , gitThunkSpecV5   , gitThunkSpecV4   , gitThunkSpecV3   , gitThunkSpecV2@@ -751,10 +771,10 @@ in fetch json |] --- | Specification for Git thunks which use a specific, pinned version--- of nixpkgs for fetching, rather than using @<nixpkgs>@ from--- @NIX_PATH@. The "v6" specs ensure that thunks can be fetched even--- when @NIX_PATH@ is unset.+-- | See 'gitThunkSpecV7'.+-- __NOTE__: v6 spec thunks are broken! They import the pinned nixpkgs+-- in an incorrect way. GitHub thunks for public repositories with no+-- submodules will still work, but update as soon as possible. gitThunkSpecV6 :: ThunkSpec gitThunkSpecV6 = mkThunkSpec "git-v6" "git.json" parseGitJsonBytes [here| # DO NOT HAND-EDIT THIS FILE@@ -776,6 +796,26 @@ in fetch json |] +-- | Specification for Git thunks which use a specific, pinned version+-- of nixpkgs for fetching, rather than using @<nixpkgs>@ from+-- @NIX_PATH@. The "v7" specs ensure that thunks can be fetched even+-- when @NIX_PATH@ is unset.+gitThunkSpecV7 :: ThunkSpec+gitThunkSpecV7 = mkThunkSpec "git-v7" "git.json" parseGitJsonBytes [i|# DO NOT HAND-EDIT THIS FILE+let fetch = {url, rev, branch ? null, sha256 ? null, fetchSubmodules ? false, private ? false, ...}:+  let realUrl = let firstChar = builtins.substring 0 1 url; in+    if firstChar == "/" then /. + url+    else if firstChar == "." then ./. + url+    else url;+  in if !fetchSubmodules && private then builtins.fetchGit {+    url = realUrl; inherit rev;+    \${if branch == null then null else "ref"} = branch;+  } else (import ${pinnedNixpkgsPath} {}).fetchgit {+    url = realUrl; inherit rev sha256;+  };+  json = builtins.fromJSON (builtins.readFile ./git.json);+in fetch json|]+ parseGitJsonBytes :: LBS.ByteString -> Either String ThunkPtr parseGitJsonBytes = parseJsonObject $ parseThunkPtr $ fmap ThunkSource_Git . parseGitSource @@ -804,7 +844,7 @@ nixBuildThunkAttrWithCache   :: ( MonadIO m      , MonadLog Output m-     , HasCliConfig m+     , HasCliConfig NixThunkError m      , MonadMask m      , MonadError NixThunkError m      , MonadFail m@@ -856,7 +896,7 @@ -- | Build a nix attribute, and cache the result if possible nixBuildAttrWithCache   :: ( MonadLog Output m-     , HasCliConfig m+     , HasCliConfig NixThunkError m      , MonadIO m      , MonadMask m      , MonadError NixThunkError m
src/Nix/Thunk/Command.hs view
@@ -64,7 +64,7 @@  runThunkCommand   :: ( MonadLog Output m-     , HasCliConfig m+     , HasCliConfig NixThunkError m      , MonadIO m      , MonadMask m      , MonadError NixThunkError m