Add new-sdist command #5389
Add new-sdist command #5389
Conversation
It is stable at least on the same machine:
|
@23Skidoo this is kinda orthogonal, but do you know who actually benefits from |
Either way, it's there now at the cost of four (soon to be two, once jgm/zip-archive#47 goes through) dependencies for |
Formally note down:
|
I need to add tests for |
To a first approximation, if the sdist hooks completely disppeared tomorrow (and obviously it's more gradual than that), the following (actively maintained and used enough to get into certain curated systems) packages would break:
I've basically managed to fix |
While I understand there are some weighty elements to this, at the same time it is blocking new-install. |
Looks good. Left some comments but they're just little niggles. Wouldn't mind having a test exercising No comment on the over-all design or the hooks stuff, which I don't understand well enough to have an informed opinion on. |
listPackageSources verbosity (flattenPackageDescription $ packageDescription pkg) knownSuffixHandlers | ||
|
||
let write = if outputFile == "-" then BSL.putStrLn else BSL.writeFile outputFile | ||
files = nub . sortBy (\(_, a) (_, b) -> compare a b) $ nonexec ++ exec |
quasicomputational
Jun 20, 2018
Contributor
sortBy (\(_, a) (_, b) -> compare a b)
=== sortOn snd
sortBy (\(_, a) (_, b) -> compare a b)
=== sortOn snd
if | ||
| listSources -> do | ||
notice verbosity $ "File manifest for package " ++ prettyShow (packageId pkg) ++ ":\n" | ||
write (BSL.pack . unlines . fmap snd $ files) |
quasicomputational
Jun 20, 2018
Contributor
--list-only
is producing an extra newline at the end of its output, e.g.:
~/src/cabal$ cabal new-run cabal -- new-sdist Cabal --list-only
[...]
tests/custom-setup/IdrisSetup.hs
tests/hackage/check.sh
tests/hackage/download.sh
tests/hackage/unpack.sh
tests/misc/ghc-supported-languages.hs
~/src/cabal$
--list-only
is producing an extra newline at the end of its output, e.g.:
~/src/cabal$ cabal new-run cabal -- new-sdist Cabal --list-only
[...]
tests/custom-setup/IdrisSetup.hs
tests/hackage/check.sh
tests/hackage/download.sh
tests/hackage/unpack.sh
tests/misc/ghc-supported-languages.hs
~/src/cabal$
typedrat
Jun 20, 2018
Author
Collaborator
Whoops, why is it putStrLn
?
Whoops, why is it putStrLn
?
perm' = case perm of | ||
Exec -> Tar.executableFilePermissions | ||
NoExec -> Tar.ordinaryFilePermissions | ||
needsEntry <- gets (notElem fileDir) |
quasicomputational
Jun 20, 2018
Contributor
Quadratic behaviour here in the number of files. Better to use a Set
.
Quadratic behaviour here in the number of files. Better to use a Set
.
typedrat
Jun 20, 2018
Author
Collaborator
I generally don't feel like being too aggressively optimizing before we know it's an issue, but adding four characters to go from O(n^2)
to O(n log n)
is worth it.
I generally don't feel like being too aggressively optimizing before we know it's an issue, but adding four characters to go from O(n^2)
to O(n log n)
is worth it.
[ optionVerbosity | ||
sdistVerbosity (\v flags -> flags { sdistVerbosity = v }) | ||
, optionDistPref | ||
sdistDistDir (\dd flags -> flags { sdistDistDir = dd }) |
quasicomputational
Jun 20, 2018
Contributor
This is claiming its default is dist
, but it actually plops the tarball in dist-newstyle
.
This is claiming its default is dist
, but it actually plops the tarball in dist-newstyle
.
typedrat
Jun 20, 2018
Author
Collaborator
That's #5380 and it's its own issue. optionDistPref
needs fixing, but that's neither here nor there for this patchset.
That's #5380 and it's its own issue. optionDistPref
needs fixing, but that's neither here nor there for this patchset.
{ commandName = "new-sdist" | ||
, commandSynopsis = "Generate a source distribution file (.tar.gz)." | ||
, commandUsage = \pname -> | ||
"Usage: " ++ pname ++ " new-sdist [FLAGS]\n" |
quasicomputational
Jun 20, 2018
Contributor
Missing the component name argument.
Missing the component name argument.
@@ -261,6 +261,15 @@ HACKAGE_SECURITY_VER="0.5.3.0"; HACKAGE_SECURITY_VER_REGEXP="0\.5\.((2\.[2-9]|[3 | |||
# >= 0.5.2 && < 0.6 | |||
TAR_VER="0.5.1.0"; TAR_VER_REGEXP="0\.5\.([1-9]|1[0-9]|0\.[3-9]|0\.1[0-9])\.?" | |||
# >= 0.5.0.3 && < 0.6 | |||
# These two are temporary: https://github.com/jgm/zip-archive/pull/47 |
quasicomputational
Jun 20, 2018
Contributor
Not actually a blocker for merging, right? I'd be OK with merging as-is and then fixing up when the PR is merged upstream.
Not actually a blocker for merging, right? I'd be OK with merging as-is and then fixing up when the PR is merged upstream.
typedrat
Jun 20, 2018
Author
Collaborator
Nope, not a blocker. That's to remind us when it does get merged (hopefully, I don't see a reason it wouldn't be).
Nope, not a blocker. That's to remind us when it does get merged (hopefully, I don't see a reason it wouldn't be).
@@ -282,6 +282,7 @@ cabalG' global_args cmd args = do | |||
| cmd `elem` ["v1-update", "outdated", "user-config", "manpage", "v1-freeze", "check"] | |||
= [ ] | |||
-- new-build commands are affected by testCabalProjectFile | |||
| cmd == "new-sdist" = [ "--project-file", testCabalProjectFile env ] |
quasicomputational
Jun 20, 2018
Contributor
Isn't this covered by the next case, catching all the new-
commands?
Isn't this covered by the next case, catching all the new-
commands?
typedrat
Jun 20, 2018
Author
Collaborator
It can’t take and is confused by ‘-j1’.
It can’t take and is confused by ‘-j1’.
, commandUsage = \pname -> | ||
"Usage: " ++ pname ++ " new-sdist [FLAGS]\n" | ||
, commandDescription = Just $ \_ -> | ||
"Generates a tarball of a package suitable for upload to Hackage." |
quasicomputational
Jun 20, 2018
Contributor
s/a package/one or more packages/?
s/a package/one or more packages/?
typedrat
Jun 20, 2018
Author
Collaborator
Whole thing needs to be pluralized, since there's one package per tarball but it can do multiple tarballs in one run.
Whole thing needs to be pluralized, since there's one package per tarball but it can do multiple tarballs in one run.
``cabal new-sdist`` takes the following flags: | ||
|
||
- ``--list-only``: Rather than creating an archive, lists files that would be included. | ||
Output is to ``stdout`` by default. |
quasicomputational
Jun 20, 2018
Contributor
Should mention it takes an optional output file argument and that making its argument -
sends it to stdout.
Should mention it takes an optional output file argument and that making its argument -
sends it to stdout.
quasicomputational
Jun 20, 2018
Contributor
Oops, sorry, I got confused. This is nonsense.
Oops, sorry, I got confused. This is nonsense.
- ``--zip``: Output an archive in ``.zip`` format. | ||
|
||
- ``--output-dir``: Sets the output dir, if a non-default one is desired. The default is | ||
``dist-newstyle/sdist/``. |
quasicomputational
Jun 20, 2018
Contributor
It's only dist-newstyle
by default, and that's controlled by a separate flag; if --builddir=foo
, then it's plopped in foo/sdist
.
It's only dist-newstyle
by default, and that's controlled by a separate flag; if --builddir=foo
, then it's plopped in foo/sdist
.
typedrat
Jun 20, 2018
•
Author
Collaborator
I mean, it is the default, and I feel like you'd know if it wasn't. BUILDDIR/sdist/
seems harder.
I mean, it is the default, and I feel like you'd know if it wasn't. BUILDDIR/sdist/
seems harder.
Oh, one more thing: can |
Ah, found a bug: |
Sorry, I spotted another thing on second look: |
I forgot to make the base path absolute before we start hopping around, that's trivial to fix and... Oh wow I have no idea how I managed to not catch that. |
I will write more tests later today. |
I can chip in with a bunch as well. Thanks for the changes so far; I think that tests and a little bit more documenting (which I'll prepare a PR into your branch for) and then it's in great shape in terms of nuts and bolts. |
[ci skip]
[ci skip]
They're not all passing, but I think that that's a bug in the code rather than the tests.
I gotta say, huge huge props to @quasicomputational for how much help they've been today. |
The Appveyor failure is specious, it's ready to merge unless there is a substantial yet heretofore unvoiced objection. |
The AppVeyor failure is actually half-legit: it's testing for a path with slashes in the |
This one wasn't actually testing what it said it was testing. Oops.
The code does the right thing, but it's slightly fragile since it depends on directory switching, so make sure it stays right.
LGTM modulo minor comments. |
|
||
``cabal new-sdist [FLAGS] [TARGETS]`` takes the crucial files needed to build ``TARGETS`` | ||
and puts them into an archive format ready for upload to Hackage. These archives are stable | ||
and two archives of the same format built from the same source will hash to the same value. |
23Skidoo
Jun 24, 2018
Member
For autogen-modules
we can't guarantee this 100% since we have no control over non-determinism in preprocessors, especially custom ones. For example, a preprocessor can add a comment with the date when the file was generated, or have output that depends on system locale settings. I guess that we can settle on saying that the behaviour is undefined when a preprocessor is non-deterministic in a way that can be observed from compiled code.
For autogen-modules
we can't guarantee this 100% since we have no control over non-determinism in preprocessors, especially custom ones. For example, a preprocessor can add a comment with the date when the file was generated, or have output that depends on system locale settings. I guess that we can settle on saying that the behaviour is undefined when a preprocessor is non-deterministic in a way that can be observed from compiled code.
typedrat
Jun 24, 2018
Author
Collaborator
autogen-modules
shouldn't (and it's a bug if they are, that probably needs a test to be sure) be included for this very reason.
autogen-modules
shouldn't (and it's a bug if they are, that probably needs a test to be sure) be included for this very reason.
23Skidoo
Jun 24, 2018
Member
You're correct! Sorry, it's getting a bit late here.
You're correct! Sorry, it's getting a bit late here.
- ``-z``, ``--null``: Only used with ``--list-only``. Separates filenames with a NUL | ||
byte instead of newlines. | ||
|
||
``new-sdist`` is inherently incompatible with sdist hooks, not due to implementation but due |
23Skidoo
Jun 24, 2018
Member
OK from me, let's deprecate them.
OK from me, let's deprecate them.
@@ -1,6 +1,8 @@ | |||
-*-change-log-*- | |||
|
|||
2.4.0.0 (current development version) | |||
* Add 'new-sdist' command (#5389). Creates stable archives based on |
23Skidoo
Jun 24, 2018
Member
Please also add a note to the Cabal changelog saying that sdist hooks are now deprecated and autogen-modules
and build-tool-depends
should be used instead.
Please also add a note to the Cabal changelog saying that sdist hooks are now deprecated and autogen-modules
and build-tool-depends
should be used instead.
@@ -165,6 +165,9 @@ data UserHooks = UserHooks { | |||
} | |||
|
|||
{-# DEPRECATED runTests "Please use the new testing interface instead!" #-} | |||
{-# DEPRECATED preSDist "SDist hooks violate the invariants of new-sdist." #-} |
23Skidoo
Jun 24, 2018
Member
Should point the user towards what they should use instead.
Should point the user towards what they should use instead.
{-# LANGUAGE RecordWildCards #-} | ||
{-# LANGUAGE TupleSections #-} | ||
{-# LANGUAGE ViewPatterns #-} | ||
module Distribution.Client.CmdSdist ( sdistCommand, sdistAction, packageToSdist, OutputFormat(..), ArchiveFormat(..) ) where |
23Skidoo
Jun 24, 2018
Member
Nitpick: please try to keep all lines <= 80 chars long. I know that this rule is not followed 100%, but we should try to follow it in new code.
Nitpick: please try to keep all lines <= 80 chars long. I know that this rule is not followed 100%, but we should try to follow it in new code.
typedrat
Jun 24, 2018
Author
Collaborator
I typically don't care much about that, but that is getting a bit silly.
I typically don't care much about that, but that is getting a bit silly.
|
||
sdistAction :: SdistFlags -> [String] -> GlobalFlags -> IO () | ||
sdistAction SdistFlags{..} targetStrings globalFlags = do | ||
let verbosity = fromFlagOrDefault normal sdistVerbosity |
23Skidoo
Jun 24, 2018
Member
If you use Emacs, you can make formatting prettier here (and elsewhere) with M-x align-regexp =
. If you don't, don't bother.
If you use Emacs, you can make formatting prettier here (and elsewhere) with M-x align-regexp =
. If you don't, don't bother.
| listSources -> "-" | ||
| otherwise -> distSdistFile distLayout (packageId pkg) archiveFormat | ||
|
||
createDirectoryIfMissing True (distSdistDirectory distLayout) |
23Skidoo
Jun 24, 2018
Member
Strictly speaking, this is not needed when outputting to stdout, but no-one probably cares.
Strictly speaking, this is not needed when outputting to stdout, but no-one probably cares.
| otherwise -> | ||
mapM_ (\pkg -> packageToSdist verbosity (distProjectRootDirectory distLayout) format (outputPath pkg) pkg) pkgs | ||
|
||
data IsExec = Exec | NoExec |
23Skidoo
Jun 24, 2018
Member
No boolean blindness, nice!
No boolean blindness, nice!
|
||
getPkg pid = case find ((== pid) . packageId) pkgs' of | ||
Just pkg -> Right pkg | ||
Nothing -> error "The impossible happened: we have a reference to a local package that isn't in localPackages." |
23Skidoo
Jun 24, 2018
Member
Perhaps add a TargetProblemImpossible
and use it instead of error
here?
Perhaps add a TargetProblemImpossible
and use it instead of error
here?
typedrat
Jun 24, 2018
Author
Collaborator
Didn't do it since it's harder to get rid of the one in flatten and I don't feel like it's worth the work when there's another five lines above.
Didn't do it since it's harder to get rid of the one in flatten and I don't feel like it's worth the work when there's another five lines above.
listPackageSources verbosity (flattenPackageDescription $ packageDescription pkg) knownSuffixHandlers | ||
|
||
let write = if outputFile == "-" | ||
then putStr . withOutputMarker verbosity . BSL.unpack |
23Skidoo
Jun 24, 2018
Member
Maybe add a helper function for this to D.S.Utils
?
Maybe add a helper function for this to D.S.Utils
?
new-sdist
is done, and so are the tests (thanks @quasicomputational). There are some unfortunate implications I don't see a way around in terms of how new-style builds work, meaning that the sdist hooks are dead. Fortunately, I don't see many cases this will actually effect. I only found three packages in a representative sample that would be "broken" (at sdist time, has no effects on end users of these packages) and honestly it'd not be much sweat off my back to fix them myself.Status:
.tar.gz
sdists.zip
sdistsCloses #4293, but does not touch #4047 or #4675, previously thought to be required. It solves the issue by simply not running preprocessors and not running
Setup configure
under the logic that whoever is downloading this sdist will be able to do it themselves in all likelihood. Doing otherwise would make it impossible to insure that the same source files will generate an identical sdist, which is required fornew-install
to work.Please include the following checklist in your PR:
[ci skip]
is used to avoid triggering the build bots.