Skip to content

Commit

Permalink
Allow absolute project file when project dir is specified
Browse files Browse the repository at this point in the history
  • Loading branch information
cydparser committed Sep 15, 2022
1 parent 57a4930 commit e95abdb
Show file tree
Hide file tree
Showing 7 changed files with 45 additions and 31 deletions.
2 changes: 1 addition & 1 deletion cabal-install/src/Distribution/Client/CmdClean.hs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ cleanCommand = CommandUI
cleanProjectDir (\path flags -> flags {cleanProjectDir = path})
(reqArg "DIR" (succeedReadE Flag) flagToList)
, option [] ["project-file"]
"Set the path of the cabal.project file (relative to the project directory)"
"Set the path of the cabal.project file (relative to the project directory when relative)"
cleanProjectFile (\pf flags -> flags {cleanProjectFile = pf})
(reqArg "FILE" (succeedReadE Flag) flagToList)
, option ['s'] ["save-config"]
Expand Down
9 changes: 7 additions & 2 deletions cabal-install/src/Distribution/Client/DistDirLayout.hs
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,10 @@ data ProjectRoot =
-- | An explicit project root. It contains the absolute project
-- root dir and the relative @cabal.project@ file (or explicit override)
| ProjectRootExplicit FilePath FilePath

-- | An explicit, absolute project root dir and an explicit, absolute
-- @cabal.project@ file.
| ProjectRootExplicitAbsolute FilePath FilePath
deriving (Eq, Show)

defaultProjectFile :: FilePath
Expand All @@ -185,8 +189,9 @@ defaultDistDirLayout projectRoot mdistDirectory =
DistDirLayout {..}
where
(projectRootDir, projectFile) = case projectRoot of
ProjectRootImplicit dir -> (dir, dir </> defaultProjectFile)
ProjectRootExplicit dir file -> (dir, dir </> file)
ProjectRootImplicit dir -> (dir, dir </> defaultProjectFile)
ProjectRootExplicit dir file -> (dir, dir </> file)
ProjectRootExplicitAbsolute dir file -> (dir, file)

distProjectRootDirectory :: FilePath
distProjectRootDirectory = projectRootDir
Expand Down
6 changes: 4 additions & 2 deletions cabal-install/src/Distribution/Client/ProjectConfig.hs
Original file line number Diff line number Diff line change
Expand Up @@ -434,7 +434,9 @@ findProjectRoot verbosity mprojectDir mprojectFile = do
Nothing -> pure $ Right (ProjectRootExplicit projectDir defaultProjectFile)

Just projectFile
| isAbsolute projectFile -> left (BadProjectRootAbsoluteFile projectFile)
| isAbsolute projectFile -> doesFileExist projectFile >>= \case
False -> left (BadProjectRootAbsoluteFile projectFile)
True -> Right . ProjectRootExplicitAbsolute dir <$> canonicalizePath projectFile

| otherwise -> doesFileExist (projectDir </> projectFile) >>= \case
False -> left (BadProjectRootDirFile dir projectFile)
Expand Down Expand Up @@ -500,7 +502,7 @@ renderBadProjectRoot = \case
"The given project directory '" <> dir <> "' does not exist."

BadProjectRootAbsoluteFile file ->
"The given project file'" <> file <> "' is an absolute path: it must be relative to the project directory."
"The given project file '" <> file <> "' does not exist."

BadProjectRootDirFile dir file ->
"The given project directory/file combination '" <> dir </> file <> "' does not exist."
Expand Down
5 changes: 3 additions & 2 deletions cabal-install/src/Distribution/Client/ProjectFlags.hs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ data ProjectFlags = ProjectFlags
-- ^ The project directory.

, flagProjectFile :: Flag FilePath
-- ^ The cabal project file path, relative to the project directory; defaults to @cabal.project@.
-- ^ The cabal project file path; defaults to @cabal.project@.
-- This path, when relative, is relative to the project directory.
-- The filename portion of the path denotes the cabal project file name, but it also
-- is the base of auxiliary project files, such as
-- @cabal.project.local@ and @cabal.project.freeze@ which are also
Expand Down Expand Up @@ -51,7 +52,7 @@ projectFlagsOptions showOrParseArgs =
flagProjectDir (\path flags -> flags { flagProjectDir = path })
(reqArg "DIR" (succeedReadE Flag) flagToList)
, option [] ["project-file"]
"Set the path of the cabal.project file (relative to the project directory)"
"Set the path of the cabal.project file (relative to the project directory when relative)"
flagProjectFile (\pf flags -> flags { flagProjectFile = pf })
(reqArg "FILE" (succeedReadE Flag) flagToList)
, option ['z'] ["ignore-project"]
Expand Down
41 changes: 22 additions & 19 deletions cabal-install/tests/UnitTests/Distribution/Client/ProjectConfig.hs
Original file line number Diff line number Diff line change
Expand Up @@ -59,12 +59,12 @@ import Distribution.Client.ProjectConfig.Legacy

import UnitTests.Distribution.Client.ArbitraryInstances
import UnitTests.Distribution.Client.TreeDiffInstances ()
import Test.Tasty
import Test.Tasty.HUnit
import Test.Tasty.QuickCheck

import Data.TreeDiff.Class
import Data.TreeDiff.QuickCheck
import Test.Tasty
import Test.Tasty.HUnit
import Test.Tasty.QuickCheck

tests :: [TestTree]
tests =
Expand Down Expand Up @@ -108,34 +108,35 @@ tests =

testFindProjectRoot :: TestTree
testFindProjectRoot = testGroup "findProjectRoot"
[ test "defaults" (cd dir) Nothing Nothing (succeeds dir file)
, test "defaults in lib" (cd libDir) Nothing Nothing (succeeds dir file)
[ test "defaults" (cd dir) Nothing Nothing (succeeds dir file)
, test "defaults in lib" (cd libDir) Nothing Nothing (succeeds dir file)

, test "explicit file" (cd dir) Nothing (Just file) (succeeds dir file)
, test "explicit file in lib" (cd libDir) Nothing (Just file) (succeeds dir file)
, test "explicit file" (cd dir) Nothing (Just file) (succeeds dir file)
, test "explicit file in lib" (cd libDir) Nothing (Just file) (succeeds dir file)

, test "other file" (cd dir) Nothing (Just fileOther) (succeeds dir fileOther)
, test "other file in lib" (cd libDir) Nothing (Just fileOther) (succeeds dir fileOther)
, test "other file" (cd dir) Nothing (Just fileOther) (succeeds dir fileOther)
, test "other file in lib" (cd libDir) Nothing (Just fileOther) (succeeds dir fileOther)

-- Deprecated use-case
, test "absolute file" Nothing Nothing (Just (dir </> file)) (succeeds dir file)
, test "absolute file" Nothing Nothing (Just absFile) (succeeds dir file)

, test "nested file" (cd dir) Nothing (Just nixFile) (succeeds dir nixFile)
, test "nested file in lib" (cd libDir) Nothing (Just nixFile) (succeeds dir nixFile)
, test "nested file" (cd dir) Nothing (Just nixFile) (succeeds dir nixFile)
, test "nested file in lib" (cd libDir) Nothing (Just nixFile) (succeeds dir nixFile)

, test "explicit dir" Nothing (Just dir) Nothing (succeeds dir file)
, test "explicit dir & file" Nothing (Just dir) (Just file) (succeeds dir file)
, test "explicit dir & nested file" Nothing (Just dir) (Just nixFile) (succeeds dir nixFile)
, test "explicit dir & nested other file" Nothing (Just dir) (Just nixOther) (succeeds dir nixOther)
, test "explicit dir" Nothing (Just dir) Nothing (succeeds dir file)
, test "explicit dir & file" Nothing (Just dir) (Just file) (succeeds dir file)
, test "explicit dir & nested file" Nothing (Just dir) (Just nixFile) (succeeds dir nixFile)
, test "explicit dir & nested other file" Nothing (Just dir) (Just nixOther) (succeeds dir nixOther)

, test "explicit dir & absolute file" Nothing (Just dir) (Just (dir </> file)) fails
, test "explicit dir & absolute file" Nothing (Just dir) (Just absFile) (succeedsWith ProjectRootExplicitAbsolute dir absFile)
]
where
dir = fixturesDir </> "project-root"
libDir = dir </> "lib"

file = defaultProjectFile
fileOther = file <.> "other"
absFile = dir </> file

nixFile = "nix" </> file
nixOther = nixFile <.> "other"
Expand All @@ -158,9 +159,11 @@ testFindProjectRoot = testGroup "findProjectRoot"

cd d = Just (withCurrentDirectory d)

succeeds projectDir projectFile result = case result of
succeeds = succeedsWith ProjectRootExplicit

succeedsWith mk projectDir projectFile result = case result of
Left err -> assertFailure $ "Expected ProjectRoot, but found " <> show err
Right pr -> pr @?= ProjectRootExplicit projectDir projectFile
Right pr -> pr @?= mk projectDir projectFile

fails result = case result of
Left _ -> pure ()
Expand Down
2 changes: 1 addition & 1 deletion changelog.d/pr-8454
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@ significance: significant
description: {

- Added --project-dir flag for specifying the project's root directory
- Deprecated using --project-file with an absolute filepath
- Deprecated using --project-file with an absolute filepath without also using --project-dir

}
11 changes: 7 additions & 4 deletions doc/cabal-project.rst
Original file line number Diff line number Diff line change
Expand Up @@ -286,9 +286,11 @@ package, and thus apply globally:
.. _cmdoption-project-dir:
.. option:: --project-dir=DIR

Specifies the path of the project directory.
When :ref:`project-file<cmdoption-project-file>` is also specified, it is
relative to this directory.
Specifies the path of the project directory. If a relative
:ref:`project-file<cmdoption-project-file>` path is also specified,
it will be resolved relative to this directory.

The project directory need not contain a ``cabal.project`` file.

This option cannot be specified via a ``cabal.project`` file.

Expand All @@ -303,7 +305,8 @@ package, and thus apply globally:
``--project-file=my.project``, then the other files that will
be probed are ``my.project.freeze`` and ``my.project.local``.

If :ref:`project-dir<cmdoption-project-dir>` is not specified, we will
If :ref:`project-dir<cmdoption-project-dir>` is not specified,
and the path is relative, we will
look for the file relative to the current working directory,
and then for the parent directory, until the project file is
found or we have hit the top of the user's home directory.
Expand Down

0 comments on commit e95abdb

Please sign in to comment.