Skip to content

Commit 0ed1218

Browse files
Fix --offline flag (#8676)
* WIP * WIP * WIP * WIP * WIP * add offline logic branch * Clean up * Formatting * Optimize * Rename test folder * Add changelog file * Fix whitespace * Add <CABAL_ERROR> normalizer tag * code review changes * Delet vs code file * Fix import * fix wrong output file --------- Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
1 parent fda8100 commit 0ed1218

File tree

15 files changed

+128
-3
lines changed

15 files changed

+128
-3
lines changed

cabal-install/src/Distribution/Client/BuildReports/Anonymous.hs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ newBuildReport os' arch' comp pkgid flags deps result =
7373
where
7474
convertInstallOutcome = case result of
7575
Left BR.PlanningFailed -> PlanningFailed
76+
Left (BR.GracefulFailure _) -> PlanningFailed
7677
Left (BR.DependentFailed p) -> DependencyFailed p
7778
Left (BR.DownloadFailed _) -> DownloadFailed
7879
Left (BR.UnpackFailed _) -> UnpackFailed

cabal-install/src/Distribution/Client/Install.hs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -968,6 +968,7 @@ printBuildFailures verbosity buildOutcomes =
968968
| (pkgid, reason) <- failed ]
969969
where
970970
printFailureReason reason = case reason of
971+
GracefulFailure msg -> msg
971972
DependentFailed pkgid -> " depends on " ++ prettyShow pkgid
972973
++ " which failed to install."
973974
DownloadFailed e -> " failed while downloading the package."

cabal-install/src/Distribution/Client/ProjectBuilding.hs

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,12 +99,15 @@ import qualified Data.ByteString as BS
9999
import qualified Data.ByteString.Lazy as LBS
100100
import qualified Data.ByteString.Lazy.Char8 as LBS.Char8
101101

102+
import qualified Text.PrettyPrint as Disp
103+
102104
import Control.Exception (Handler (..), SomeAsyncException, assert, catches, handle)
103105
import System.Directory (canonicalizePath, createDirectoryIfMissing, doesDirectoryExist, doesFileExist, removeFile, renameDirectory)
104106
import System.FilePath (dropDrive, makeRelative, normalise, takeDirectory, (<.>), (</>))
105107
import System.IO (IOMode (AppendMode), Handle, withFile)
106108

107109
import Distribution.Compat.Directory (listDirectory)
110+
import Distribution.Simple.Flag (fromFlagOrDefault)
108111

109112

110113
------------------------------------------------------------------------------
@@ -559,6 +562,7 @@ invalidatePackageRegFileMonitor PackageFileMonitor{pkgFileMonitorReg} =
559562
-- It requires the 'BuildStatusMap' gathered by 'rebuildTargetsDryRun'.
560563
--
561564
rebuildTargets :: Verbosity
565+
-> ProjectConfig
562566
-> DistDirLayout
563567
-> StoreDirLayout
564568
-> ElaboratedInstallPlan
@@ -567,6 +571,9 @@ rebuildTargets :: Verbosity
567571
-> BuildTimeSettings
568572
-> IO BuildOutcomes
569573
rebuildTargets verbosity
574+
ProjectConfig {
575+
projectConfigBuildOnly = config
576+
}
570577
distDirLayout@DistDirLayout{..}
571578
storeDirLayout
572579
installPlan
@@ -578,8 +585,9 @@ rebuildTargets verbosity
578585
buildSettings@BuildTimeSettings{
579586
buildSettingNumJobs,
580587
buildSettingKeepGoing
581-
} = do
582-
588+
}
589+
| fromFlagOrDefault False (projectConfigOfflineMode config) && not (null packagesToDownload) = return offlineError
590+
| otherwise = do
583591
-- Concurrency control: create the job controller and concurrency limits
584592
-- for downloading, building and installing.
585593
jobControl <- if isParallelBuild
@@ -637,6 +645,32 @@ rebuildTargets verbosity
637645
, elabSetupPackageDBStack elab ]
638646
]
639647

648+
offlineError :: BuildOutcomes
649+
offlineError = Map.fromList . map makeBuildOutcome $ packagesToDownload
650+
where
651+
makeBuildOutcome :: ElaboratedConfiguredPackage -> (UnitId, BuildOutcome)
652+
makeBuildOutcome ElaboratedConfiguredPackage {
653+
elabUnitId,
654+
elabPkgSourceId = PackageIdentifier { pkgName, pkgVersion }
655+
} = (elabUnitId, Left (BuildFailure {
656+
buildFailureLogFile = Nothing,
657+
buildFailureReason = GracefulFailure $ makeError pkgName pkgVersion
658+
}))
659+
makeError :: PackageName -> Version -> String
660+
makeError n v = "--offline was specified, hence refusing to download the package: "
661+
++ unPackageName n
662+
++ " version " ++ Disp.render (pretty v)
663+
664+
packagesToDownload :: [ElaboratedConfiguredPackage]
665+
packagesToDownload = [elab | InstallPlan.Configured elab <- InstallPlan.reverseTopologicalOrder installPlan,
666+
isRemote $ elabPkgSourceLocation elab]
667+
where
668+
isRemote :: PackageLocation a -> Bool
669+
isRemote (RemoteTarballPackage _ _) = True
670+
isRemote (RepoTarballPackage {}) = True
671+
isRemote (RemoteSourceRepoPackage _ _) = True
672+
isRemote _ = False
673+
640674

641675
-- | Create a package DB if it does not currently exist. Note that this action
642676
-- is /not/ safe to run concurrently.

cabal-install/src/Distribution/Client/ProjectBuilding/Types.hs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,7 @@ instance Exception BuildFailure
192192
-- | Detail on the reason that a package failed to build.
193193
--
194194
data BuildFailureReason = DependentFailed PackageId
195+
| GracefulFailure String
195196
| DownloadFailed SomeException
196197
| UnpackFailed SomeException
197198
| ConfigureFailed SomeException

cabal-install/src/Distribution/Client/ProjectOrchestration.hs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,7 @@ runProjectBuildPhase verbosity
400400
ProjectBaseContext{..} ProjectBuildContext {..} =
401401
fmap (Map.union (previousBuildOutcomes pkgsBuildStatus)) $
402402
rebuildTargets verbosity
403+
projectConfig
403404
distDirLayout
404405
(cabalStoreDirLayout cabalDirLayout)
405406
elaboratedPlanToExecute
@@ -1019,6 +1020,7 @@ writeBuildReports settings buildContext plan buildOutcomes = do
10191020
fromPlanPackage (InstallPlan.Configured pkg) (Just result) =
10201021
let installOutcome = case result of
10211022
Left bf -> case buildFailureReason bf of
1023+
GracefulFailure _ -> BuildReports.PlanningFailed
10221024
DependentFailed p -> BuildReports.DependencyFailed p
10231025
DownloadFailed _ -> BuildReports.DownloadFailed
10241026
UnpackFailed _ -> BuildReports.UnpackFailed
@@ -1209,6 +1211,7 @@ dieOnBuildFailures verbosity currentCommand plan buildOutcomes
12091211
TestsFailed _ -> "Tests failed for " ++ pkgstr
12101212
BenchFailed _ -> "Benchmarks failed for " ++ pkgstr
12111213
InstallFailed _ -> "Failed to build " ++ pkgstr
1214+
GracefulFailure msg -> msg
12121215
DependentFailed depid
12131216
-> "Failed to build " ++ prettyShow (packageId pkg)
12141217
++ " because it depends on " ++ prettyShow depid
@@ -1301,6 +1304,7 @@ dieOnBuildFailures verbosity currentCommand plan buildOutcomes
13011304
TestsFailed e -> Just e
13021305
BenchFailed e -> Just e
13031306
InstallFailed e -> Just e
1307+
GracefulFailure _ -> Nothing
13041308
DependentFailed _ -> Nothing
13051309

13061310
data BuildFailurePresentation =

cabal-install/src/Distribution/Client/Types/BuildResults.hs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ type BuildOutcomes = Map UnitId BuildOutcome
2525

2626
data BuildFailure = PlanningFailed
2727
| DependentFailed PackageId
28+
| GracefulFailure String
2829
| DownloadFailed SomeException
2930
| UnpackFailed SomeException
3031
| ConfigureFailed SomeException

cabal-install/tests/IntegrationTests2.hs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1715,7 +1715,7 @@ planProject testdir cliConfig = do
17151715
elaboratedShared)
17161716

17171717
executePlan :: PlanDetails -> IO (ElaboratedInstallPlan, BuildOutcomes)
1718-
executePlan ((distDirLayout, cabalDirLayout, _, _, buildSettings),
1718+
executePlan ((distDirLayout, cabalDirLayout, config, _, buildSettings),
17191719
elaboratedPlan,
17201720
elaboratedShared) = do
17211721

@@ -1741,6 +1741,7 @@ executePlan ((distDirLayout, cabalDirLayout, _, _, buildSettings),
17411741

17421742
buildOutcomes <-
17431743
rebuildTargets verbosity
1744+
config
17441745
distDirLayout
17451746
(cabalStoreDirLayout cabalDirLayout)
17461747
elaboratedPlan''
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import P (p)
2+
3+
main :: IO ()
4+
main = print p
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
packages: ./main.cabal
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
cabal-version: 3.0
2+
name: current
3+
version: 0.1.0.0
4+
license: MIT
5+
author: Colton Clemmer
6+
maintainer: [email protected]
7+
-- copyright:
8+
build-type: Simple
9+
extra-doc-files: CHANGELOG.md
10+
-- extra-source-files:
11+
12+
common warnings
13+
ghc-options: -Wall
14+
15+
executable current
16+
import: warnings
17+
main-is: Main.hs
18+
build-depends: base, remote
19+
default-language: Haskell2010
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# cabal v2-update
2+
Downloading the latest package list from test-local-repo
3+
# cabal v2-build
4+
Resolving dependencies...
5+
Build profile: -w ghc-<GHCVER> -O1
6+
In order, the following will be built:
7+
- remote-0.1.0.0 (lib) (requires build)
8+
- current-0.1.0.0 (exe:current) (first run)
9+
Error: cabal: --offline was specified, hence refusing to download the package: remote version 0.1.0.0.
10+
# cabal v2-build
11+
Build profile: -w ghc-<GHCVER> -O1
12+
In order, the following will be built:
13+
- remote-0.1.0.0 (lib) (requires build)
14+
- current-0.1.0.0 (exe:current) (first run)
15+
Configuring library for remote-0.1.0.0..
16+
Preprocessing library for remote-0.1.0.0..
17+
Building library for remote-0.1.0.0..
18+
Installing library in <PATH>
19+
Configuring executable 'current' for current-0.1.0.0..
20+
Preprocessing executable 'current' for current-0.1.0.0..
21+
Building executable 'current' for current-0.1.0.0..
22+
# cabal v2-build
23+
Up to date
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import Test.Cabal.Prelude
2+
3+
main = withShorterPathForNewBuildStore $ \storeDir ->
4+
cabalTest $ do
5+
skipUnlessGhcVersion ">= 8.1"
6+
skipIfWindows
7+
withProjectFile "cabal.repo.project" $ do
8+
withRepo "repo" $ do
9+
fails $ cabalG ["--store-dir=" ++ storeDir] "v2-build" ["current", "--offline"]
10+
cabalG ["--store-dir=" ++ storeDir] "v2-build" ["current"]
11+
cabalG ["--store-dir=" ++ storeDir] "v2-build" ["current", "--offline"]
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module P (p) where
2+
3+
p = "Foo"
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
cabal-version: 3.0
2+
name: remote
3+
version: 0.1.0.0
4+
license: MIT
5+
author: Colton Clemmer
6+
maintainer: [email protected]
7+
build-type: Simple
8+
extra-doc-files: CHANGELOG.md
9+
10+
library
11+
build-depends: base
12+
exposed-modules: P
13+
default-language: Haskell2010

changelog.d/pr-8676

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
synopsis: Adds functionality for the --offline flag with the "build" command.
2+
packages: cabal-install
3+
prs: #8676
4+
5+
description: {
6+
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.
7+
Additionally there is a new PackageTest for the flag using the build command.
8+
}

0 commit comments

Comments
 (0)