Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix --offline flag (backport #8676) #8838

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ newBuildReport os' arch' comp pkgid flags deps result =
where
convertInstallOutcome = case result of
Left BR.PlanningFailed -> PlanningFailed
Left (BR.GracefulFailure _) -> PlanningFailed
Left (BR.DependentFailed p) -> DependencyFailed p
Left (BR.DownloadFailed _) -> DownloadFailed
Left (BR.UnpackFailed _) -> UnpackFailed
Expand Down
1 change: 1 addition & 0 deletions cabal-install/src/Distribution/Client/Install.hs
Original file line number Diff line number Diff line change
Expand Up @@ -968,6 +968,7 @@ printBuildFailures verbosity buildOutcomes =
| (pkgid, reason) <- failed ]
where
printFailureReason reason = case reason of
GracefulFailure msg -> msg
DependentFailed pkgid -> " depends on " ++ prettyShow pkgid
++ " which failed to install."
DownloadFailed e -> " failed while downloading the package."
Expand Down
38 changes: 36 additions & 2 deletions cabal-install/src/Distribution/Client/ProjectBuilding.hs
Original file line number Diff line number Diff line change
Expand Up @@ -99,12 +99,15 @@ import qualified Data.ByteString as BS
import qualified Data.ByteString.Lazy as LBS
import qualified Data.ByteString.Lazy.Char8 as LBS.Char8

import qualified Text.PrettyPrint as Disp

import Control.Exception (Handler (..), SomeAsyncException, assert, catches, handle)
import System.Directory (canonicalizePath, createDirectoryIfMissing, doesDirectoryExist, doesFileExist, removeFile, renameDirectory)
import System.FilePath (dropDrive, makeRelative, normalise, takeDirectory, (<.>), (</>))
import System.IO (IOMode (AppendMode), Handle, withFile)

import Distribution.Compat.Directory (listDirectory)
import Distribution.Simple.Flag (fromFlagOrDefault)


------------------------------------------------------------------------------
Expand Down Expand Up @@ -559,6 +562,7 @@ invalidatePackageRegFileMonitor PackageFileMonitor{pkgFileMonitorReg} =
-- It requires the 'BuildStatusMap' gathered by 'rebuildTargetsDryRun'.
--
rebuildTargets :: Verbosity
-> ProjectConfig
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

-> DistDirLayout
-> StoreDirLayout
-> ElaboratedInstallPlan
Expand All @@ -567,6 +571,9 @@ rebuildTargets :: Verbosity
-> BuildTimeSettings
-> IO BuildOutcomes
rebuildTargets verbosity
ProjectConfig {
projectConfigBuildOnly = config
}
distDirLayout@DistDirLayout{..}
storeDirLayout
installPlan
Expand All @@ -578,8 +585,9 @@ rebuildTargets verbosity
buildSettings@BuildTimeSettings{
buildSettingNumJobs,
buildSettingKeepGoing
} = do

}
| fromFlagOrDefault False (projectConfigOfflineMode config) && not (null packagesToDownload) = return offlineError
| otherwise = do
-- Concurrency control: create the job controller and concurrency limits
-- for downloading, building and installing.
jobControl <- if isParallelBuild
Expand Down Expand Up @@ -637,6 +645,32 @@ rebuildTargets verbosity
, elabSetupPackageDBStack elab ]
]

offlineError :: BuildOutcomes
offlineError = Map.fromList . map makeBuildOutcome $ packagesToDownload
where
makeBuildOutcome :: ElaboratedConfiguredPackage -> (UnitId, BuildOutcome)
makeBuildOutcome ElaboratedConfiguredPackage {
elabUnitId,
elabPkgSourceId = PackageIdentifier { pkgName, pkgVersion }
} = (elabUnitId, Left (BuildFailure {
buildFailureLogFile = Nothing,
buildFailureReason = GracefulFailure $ makeError pkgName pkgVersion
}))
makeError :: PackageName -> Version -> String
makeError n v = "--offline was specified, hence refusing to download the package: "
++ unPackageName n
++ " version " ++ Disp.render (pretty v)

packagesToDownload :: [ElaboratedConfiguredPackage]
packagesToDownload = [elab | InstallPlan.Configured elab <- InstallPlan.reverseTopologicalOrder installPlan,
isRemote $ elabPkgSourceLocation elab]
where
isRemote :: PackageLocation a -> Bool
isRemote (RemoteTarballPackage _ _) = True
isRemote (RepoTarballPackage {}) = True
isRemote (RemoteSourceRepoPackage _ _) = True
isRemote _ = False


-- | Create a package DB if it does not currently exist. Note that this action
-- is /not/ safe to run concurrently.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,7 @@ instance Exception BuildFailure
-- | Detail on the reason that a package failed to build.
--
data BuildFailureReason = DependentFailed PackageId
| GracefulFailure String
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

| DownloadFailed SomeException
| UnpackFailed SomeException
| ConfigureFailed SomeException
Expand Down
4 changes: 4 additions & 0 deletions cabal-install/src/Distribution/Client/ProjectOrchestration.hs
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,7 @@ runProjectBuildPhase verbosity
ProjectBaseContext{..} ProjectBuildContext {..} =
fmap (Map.union (previousBuildOutcomes pkgsBuildStatus)) $
rebuildTargets verbosity
projectConfig
distDirLayout
(cabalStoreDirLayout cabalDirLayout)
elaboratedPlanToExecute
Expand Down Expand Up @@ -1018,6 +1019,7 @@ writeBuildReports settings buildContext plan buildOutcomes = do
fromPlanPackage (InstallPlan.Configured pkg) (Just result) =
let installOutcome = case result of
Left bf -> case buildFailureReason bf of
GracefulFailure _ -> BuildReports.PlanningFailed
DependentFailed p -> BuildReports.DependencyFailed p
DownloadFailed _ -> BuildReports.DownloadFailed
UnpackFailed _ -> BuildReports.UnpackFailed
Expand Down Expand Up @@ -1208,6 +1210,7 @@ dieOnBuildFailures verbosity currentCommand plan buildOutcomes
TestsFailed _ -> "Tests failed for " ++ pkgstr
BenchFailed _ -> "Benchmarks failed for " ++ pkgstr
InstallFailed _ -> "Failed to build " ++ pkgstr
GracefulFailure msg -> msg
DependentFailed depid
-> "Failed to build " ++ prettyShow (packageId pkg)
++ " because it depends on " ++ prettyShow depid
Expand Down Expand Up @@ -1300,6 +1303,7 @@ dieOnBuildFailures verbosity currentCommand plan buildOutcomes
TestsFailed e -> Just e
BenchFailed e -> Just e
InstallFailed e -> Just e
GracefulFailure _ -> Nothing
DependentFailed _ -> Nothing

data BuildFailurePresentation =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ type BuildOutcomes = Map UnitId BuildOutcome

data BuildFailure = PlanningFailed
| DependentFailed PackageId
| GracefulFailure String
| DownloadFailed SomeException
| UnpackFailed SomeException
| ConfigureFailed SomeException
Expand Down
3 changes: 2 additions & 1 deletion cabal-install/tests/IntegrationTests2.hs
Original file line number Diff line number Diff line change
Expand Up @@ -1736,7 +1736,7 @@ planProject testdir cliConfig = do
elaboratedShared)

executePlan :: PlanDetails -> IO (ElaboratedInstallPlan, BuildOutcomes)
executePlan ((distDirLayout, cabalDirLayout, _, _, buildSettings),
executePlan ((distDirLayout, cabalDirLayout, config, _, buildSettings),
elaboratedPlan,
elaboratedShared) = do

Expand All @@ -1762,6 +1762,7 @@ executePlan ((distDirLayout, cabalDirLayout, _, _, buildSettings),

buildOutcomes <-
rebuildTargets verbosity
config
distDirLayout
(cabalStoreDirLayout cabalDirLayout)
elaboratedPlan''
Expand Down
4 changes: 4 additions & 0 deletions cabal-testsuite/PackageTests/OfflineFlag/Main.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import P (p)

main :: IO ()
main = print p
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
packages: ./main.cabal
19 changes: 19 additions & 0 deletions cabal-testsuite/PackageTests/OfflineFlag/main.cabal
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
cabal-version: 3.0
name: current
version: 0.1.0.0
license: MIT
author: Colton Clemmer
maintainer: coltonclemmerdev@gmail.com
-- copyright:
build-type: Simple
extra-doc-files: CHANGELOG.md
-- extra-source-files:

common warnings
ghc-options: -Wall

executable current
import: warnings
main-is: Main.hs
build-depends: base, remote
default-language: Haskell2010
23 changes: 23 additions & 0 deletions cabal-testsuite/PackageTests/OfflineFlag/offlineFlag.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# cabal v2-update
Downloading the latest package list from test-local-repo
# cabal v2-build
Resolving dependencies...
Build profile: -w ghc-<GHCVER> -O1
In order, the following will be built:
- remote-0.1.0.0 (lib) (requires build)
- current-0.1.0.0 (exe:current) (first run)
Error: cabal: --offline was specified, hence refusing to download the package: remote version 0.1.0.0.
# cabal v2-build
Build profile: -w ghc-<GHCVER> -O1
In order, the following will be built:
- remote-0.1.0.0 (lib) (requires build)
- current-0.1.0.0 (exe:current) (first run)
Configuring library for remote-0.1.0.0..
Preprocessing library for remote-0.1.0.0..
Building library for remote-0.1.0.0..
Installing library in <PATH>
Configuring executable 'current' for current-0.1.0.0..
Preprocessing executable 'current' for current-0.1.0.0..
Building executable 'current' for current-0.1.0.0..
# cabal v2-build
Up to date
11 changes: 11 additions & 0 deletions cabal-testsuite/PackageTests/OfflineFlag/offlineFlag.test.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import Test.Cabal.Prelude

main = withShorterPathForNewBuildStore $ \storeDir ->
cabalTest $ do
skipUnlessGhcVersion ">= 8.1"
skipIfWindows
withProjectFile "cabal.repo.project" $ do
withRepo "repo" $ do
fails $ cabalG ["--store-dir=" ++ storeDir] "v2-build" ["current", "--offline"]
cabalG ["--store-dir=" ++ storeDir] "v2-build" ["current"]
cabalG ["--store-dir=" ++ storeDir] "v2-build" ["current", "--offline"]
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module P (p) where

p = "Foo"
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
cabal-version: 3.0
name: remote
version: 0.1.0.0
license: MIT
author: Colton Clemmer
maintainer: coltonclemmerdev@gmail.com
build-type: Simple
extra-doc-files: CHANGELOG.md

library
build-depends: base
exposed-modules: P
default-language: Haskell2010
8 changes: 8 additions & 0 deletions changelog.d/pr-8676
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
synopsis: Adds functionality for the --offline flag with the "build" command.
packages: cabal-install
prs: #8676

description: {
The --offline flag previously created in #2578 but was only implemented for the install command even thought the flag didn't throw an error whenever the build command was run. This PR adds functionality for the --offline flag with the build command.
Additionally there is a new PackageTest for the flag using the build command.
}