@@ -61,11 +61,14 @@ import System.IO
6161import System.IO.Error
6262import System.IO.Temp
6363import System.Posix (getSymbolicLinkStatus, modificationTime)
64−import System.Process
64+import System.Process (StdStream (CreatePipe), callProcess, createProcess, proc, readProcess, std_err,
65+ std_out, waitForProcess)
6566
6667import Development.Placeholders
6768import Obelisk.Command.Utils
6869
70+import Obelisk.Command.CLI (failWith, putError, putWarning, withSpinner)
71+
6972--TODO: Support symlinked thunk data
7073data ThunkData
7174 = ThunkData_Packed ThunkPtr
@@ -132,7 +135,7 @@ getNixSha256ForUriUnpacked uri = do
132135 hPutStrLn stdout =<< hGetContents out
133136 hPutStrLn stderr =<< hGetContents err
134137 --TODO: actual error
135− fail $ "nix-prefetch-url"
138+ failWith $ "nix-prefetch-url"
136139 T.strip <$> T.hGetContents out
137140
138141-- | Get the latest revision available from the given source
@@ -322,10 +325,10 @@ createThunkWithLatest target s = do
322325updateThunkToLatest :: FilePath -> IO ()
323326updateThunkToLatest target = do
324327 (overwrite, ptr) <- readThunk target >>= \case
325− Left err -> fail $ "thunk update: " <> show err
326− Right c -> return $ case c of
327− ThunkData_Packed t -> (target, t)
328− ThunkData_Checkout _ -> fail "cannot update an unpacked thunk"
328+ Left err -> failWith $ T.pack $ "thunk update: " <> show err
329+ Right c -> case c of
330+ ThunkData_Packed t -> return (target, t)
331+ ThunkData_Checkout _ -> failWith "cannot update an unpacked thunk"
329332 let src = _thunkPtr_source ptr
330333 rev <- getLatestRev src
331334 overwriteThunk overwrite $ ThunkPtr
@@ -402,7 +405,7 @@ nixBuildThunkAttrWithCache thunkDir attr = do
402405 --This should be guaranteed by the command argument parser.
403406 let cacheErrHandler e
404407 | isDoesNotExistError e = return Nothing -- expected from a cache miss
405− | otherwise = hPutStrLn stderr (displayException e) >> return Nothing
408+ | otherwise = putError (T.pack $ displayException e) >> return Nothing
406409 cacheDir = thunkDir </> ".attr-cache"
407410 cachePath = cacheDir </> attr <.> "out"
408411 createDirectoryIfMissing False cacheDir
@@ -415,7 +418,7 @@ nixBuildThunkAttrWithCache thunkDir attr = do
415418 case cacheHit of
416419 Just c -> return c
417420 Nothing -> do
418− hPutStrLn stderr (mconcat [thunkDir, ": ", attr, " not cached, building ..."])
421+ putWarning $ T.pack $ mconcat [thunkDir, ": ", attr, " not cached, building ..."]
419422 _ <- nixBuild $ def
420423 { _nixBuildConfig_target = Target
421424 { _target_path = thunkDir
@@ -447,31 +450,33 @@ nixBuildAttrWithCache exprPath attr = do
447450unpackThunk :: FilePath
448451 -> IO ()
449452unpackThunk thunkDir = readThunk thunkDir >>= \case
450− Left err -> fail $ "thunk unpack: " <> show err
453+ Left err -> failWith $ "thunk unpack: " <> (T.pack $ show err)
451454 --TODO: Overwrite option that rechecks out thunk; force option to do so even if working directory is dirty
452− Right (ThunkData_Checkout _) -> fail "thunk unpack: thunk is already unpacked"
455+ Right (ThunkData_Checkout _) -> failWith "thunk unpack: thunk is already unpacked"
453456 Right (ThunkData_Packed tptr) -> case _thunkPtr_source tptr of
454457 ThunkSource_GitHub s | (thunkParent, thunkName) <- splitFileName thunkDir -> withTempDirectory thunkParent thunkName $ \tmpRepo -> do
455458 mauth <- getHubAuth "github.com"
456459 repoResult <- executeRequestMaybe mauth $ repositoryR (_gitHubSource_owner s) (_gitHubSource_repo s)
457460 githubURI <- either throwIO (return . repoSshUrl) repoResult >>= \case
458− Nothing -> fail "Cannot determine clone URI for thunk source"
461+ Nothing -> failWith "Cannot determine clone URI for thunk source"
459462 Just c -> return $ T.unpack $ getUrl c
460− callProcess "hub" --TODO: Depend on hub explicitly
461− [ "clone"
462− , "-n"
463− , githubURI
464− , tmpRepo
465− ]
463+ withSpinner "Cloning from GitHub ..." (Just $ "Cloned " <> githubURI) $ do
464+ callProcess "hub" --TODO: Depend on hub explicitly
465+ [ "clone"
466+ , "-n"
467+ , githubURI
468+ , tmpRepo
469+ ]
466470 let obGitDir = tmpRepo </> ".git" </> "obelisk"
467471 --If this directory already exists then something is weird and we should fail
468472 createDirectory obGitDir
469− callProcess "cp"
470− [ "-r"
471− , "-T"
472− , thunkDir </> "."
473− , obGitDir </> "orig-thunk"
474− ]
473+ withSpinner "Copying thunk ..." Nothing $ do
474+ callProcess "cp"
475+ [ "-r"
476+ , "-T"
477+ , thunkDir </> "."
478+ , obGitDir </> "orig-thunk"
479+ ]
475480 let checkoutOptions = concat
476481 [ ["-C", tmpRepo]
477482 , pure "checkout"
@@ -498,8 +503,8 @@ packThunk :: FilePath
498503 -> String
499504 -> IO ()
500505packThunk thunkDir upstream = readThunk thunkDir >>= \case
501− Left err -> fail $ "thunk pack: " <> show err
502− Right (ThunkData_Packed _) -> fail "pack: thunk is already packed"
506+ Left err -> failWith $ T.pack $ "thunk pack: " <> show err
507+ Right (ThunkData_Packed _) -> failWith "pack: thunk is already packed"
503508 Right (ThunkData_Checkout _) -> do
504509 thunkPtr <- getThunkPtr thunkDir upstream
505510 callProcess "rm"
@@ -515,7 +520,7 @@ getThunkPtr thunkDir upstream = do
515520 False -> do
516521 statusDebug <- readProcess "hub"
517522 [ "-C", thunkDir, "status", "--ignored" ] ""
518− fail $ unlines $
523+ failWith $ T.pack $ unlines $
519524 [ "thunk pack: thunk checkout contains unsaved modifications"
520525 , "git status:"
521526 ] ++ lines statusDebug
@@ -525,7 +530,7 @@ getThunkPtr thunkDir upstream = do
525530 stashOutput <- readProcess "hub" [ "-C", thunkDir, "stash", "list" ] ""
526531 case null stashOutput of
527532 False -> do
528− fail $ unlines $
533+ failWith $ T.pack $ unlines $
529534 [ "thunk pack: thunk checkout has stashes"
530535 , "git stash list:"
531536 ] ++ lines stashOutput
@@ -539,7 +544,7 @@ getThunkPtr thunkDir upstream = do
539544 remotes <- lines <$> readProcess "hub" [ "-C", thunkDir, "remote" ] ""
540545 --Check that the upstream specified actually exists
541546 case L.find (== upstream) remotes of
542− Nothing -> fail $ "thunk pack: upstream " <> upstream <> " does not exist"
547+ Nothing -> failWith $ T.pack $ "thunk pack: upstream " <> upstream <> " does not exist"
543548 Just _ -> return ()
544549 -- iterate over cartesian product
545550 forM_ repoHeads $ \hd -> do
@@ -553,7 +558,7 @@ getThunkPtr thunkDir upstream = do
553558 , "remotes/" <> rm <> "/" <> hd
554559 ] ""
555560 case remoteMergeRev == localRev of
556− False -> fail $ mconcat [ "thunk unpack: branch ", hd, " has not been pushed to ", rm ]
561+ False -> failWith $ T.pack $ mconcat [ "thunk unpack: branch ", hd, " has not been pushed to ", rm ]
557562 True -> return ()
558563
559564 --We assume it's safe to pack the thunk at this point
@@ -566,7 +571,7 @@ getThunkPtr thunkDir upstream = do
566571 mRemoteUri = parseURIReference remoteUri'
567572 <|> parseSshShorthand remoteUri'
568573 thunkPtr <- case mRemoteUri of
569− Nothing -> fail uriParseFailure
574+ Nothing -> failWith $ T.pack uriParseFailure
570575 Just remoteUri -> do
571576 refs <- fmap (refsToTuples . words) . lines <$> readProcess "hub"
572577 [ "-C"
@@ -626,7 +631,7 @@ getThunkPtr thunkDir upstream = do
626631 case uriScheme u of
627632 "https:" -> return ()
628633 "git:" -> return ()
629− _ -> fail $ "thunk pack: obelisk currently only supports https and git protocols for non-GitHub remotes"
634+ _ -> failWith "thunk pack: obelisk currently only supports https and git protocols for non-GitHub remotes"
630635 $notImplemented
631636 parseSshShorthand uri' = do
632637 -- This is what git does to check that the remote