Skip to content

Commit

Permalink
Re #6270 Step 4 Upload document archive to Hackage
Browse files Browse the repository at this point in the history
  • Loading branch information
mpilgrem committed Oct 12, 2023
1 parent e4d5b0a commit fd8d69e
Show file tree
Hide file tree
Showing 6 changed files with 315 additions and 136 deletions.
93 changes: 64 additions & 29 deletions doc/upload_command.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,23 @@

# The `stack upload` command

Either (one or more packages)

~~~text
stack upload [DIR] [--pvp-bounds PVP-BOUNDS] [--ignore-check]
[--[no-]test-tarball] [--tar-dir ARG] [--candidate]
~~~

or (documentation for a package)

~~~text
stack upload DIR (-d|--documentation) [--candidate] [--setup-info-yaml URL]
[--snapshot-location-base URL]
~~~

## Upload one or more packages

Hackage accepts packages for uploading in a standard form, a compressed archive
('tarball') in the format produced by Cabal's `sdist` action.

Expand All @@ -18,6 +30,56 @@ current working directory is the root directory of your project:
stack upload .
~~~

### `--ignore-check` flag

Pass the flag to disable checks of the package for common mistakes. By default,
the command will check the package for common mistakes.

### `--pvp-bounds` option

The `--pvp-bounds <pvp_bounds_mode>` option determines whether and, if so, how
PVP version bounds should be added to the Cabal file of the package. The
available modes for basic use are: `none`, `lower`, `upper`, and `both`. The
available modes for use with Cabal file revisions are `lower-revision`,
`upper-revision` and `both-revision`.

For futher information, see the
[YAML configuration](yaml_configuration.md#pvp-bounds) documentation.

### `--tar-dir` option

The `--tar-dir <path_to_directory>` option determines whether the package
archive should be copied to the specified directory.

### `--[no-]test-tarball` flag

Default: Disabled

Set the flag to cause Stack to test the resulting package archive, by attempting
to build it.

## Upload documentation for a package

:octicons-beaker-24: Experimental

:octicons-tag-24: UNRELEASED

Hackage accepts documentation for a package for uploading in a standard form and
in a compressed archive ('tarball') in the `.tar.gz` format.

For further information about how to create such an archive file, see the
documentation for the
[`stack haddock --haddock-for-hackage`](build_command.md#-no-haddock-for-haddock-flag)
command.

`stack upload <package_directory> --documentation` uploads an existing archive
file of documentation for the specified package to Hackage. For example, if the
current working directory is the root directory of your project:

~~~text
stack upload . --documentation
~~~

## The `HACKAGE_USERNAME` and `HACKAGE_PASSWORD` environment variables

[:octicons-tag-24: 2.3.1](https://github.com/commercialhaskell/stack/releases/tag/v2.3.1)
Expand Down Expand Up @@ -71,32 +133,5 @@ example:
## `--candidate` flag

Pass the flag to upload a
[package candidate](http://hackage.haskell.org/upload#candidates).

## `--ignore-check` flag

Pass the flag to disable checks of the package for common mistakes. By default,
the command will check the package for common mistakes.

## `--pvp-bounds` option

The `--pvp-bounds <pvp_bounds_mode>` option determines whether and, if so, how
PVP version bounds should be added to the Cabal file of the package. The
available modes for basic use are: `none`, `lower`, `upper`, and `both`. The
available modes for use with Cabal file revisions are `lower-revision`,
`upper-revision` and `both-revision`.

For futher information, see the
[YAML configuration](yaml_configuration.md#pvp-bounds) documentation.

## `--tar-dir` option

The `--tar-dir <path_to_directory>` option determines whether the package
archive should be copied to the specified directory.

## `--[no-]test-tarball` flag

Default: Disabled

Set the flag to cause Stack to test the resulting package archive, by attempting
to build it.
[package candidate](http://hackage.haskell.org/upload#candidates) or
documentation for a package candidate.
4 changes: 3 additions & 1 deletion src/Network/HTTP/StackClient.hs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ module Network.HTTP.StackClient
, setRequestCheckStatus
, setRequestMethod
, setRequestHeader
, setRequestHeaders
, addRequestHeader
, setRequestBody
, getResponseHeaders
Expand Down Expand Up @@ -92,7 +93,8 @@ import qualified Network.HTTP.Download as Download
import Network.HTTP.Simple
( addRequestHeader, getResponseBody, getResponseHeaders
, getResponseStatusCode, setRequestBody
, setRequestCheckStatus, setRequestHeader, setRequestMethod
, setRequestCheckStatus, setRequestHeader, setRequestHeaders
, setRequestMethod
)
import qualified Network.HTTP.Simple
( httpJSON, httpLbs, httpNoBody, httpSink, withResponse )
Expand Down
2 changes: 1 addition & 1 deletion src/Stack/CLI.hs
Original file line number Diff line number Diff line change
Expand Up @@ -511,7 +511,7 @@ commandLineHandler currentDir progName isInterpreter =

upload = addCommand'
"upload"
"Upload a package to Hackage."
"Upload one or more packages, or documentation for a package, to Hackage."
uploadCmd
uploadOptsParser

Expand Down
49 changes: 39 additions & 10 deletions src/Stack/Options/UploadParser.hs
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,48 @@ module Stack.Options.UploadParser
( uploadOptsParser
) where

import Options.Applicative ( Parser, flag, help, long )
import Stack.Options.SDistParser ( sdistOptsParser )
import Options.Applicative
( Parser, completer, flag, help, idm, long, metavar, short
, strArgument, strOption, switch
)
import Options.Applicative.Builder.Extra ( boolFlags, dirCompleter )
import Stack.Options.HpcReportParser ( pvpBoundsOption )
import Stack.Prelude
import Stack.Upload ( UploadOpts (..), UploadVariant (..) )

-- | Parse command line arguments for Stack's @upload@ command.
uploadOptsParser :: Parser UploadOpts
uploadOptsParser =
UploadOpts
<$> sdistOptsParser
<*> uploadVariant
where
uploadVariant = flag Publishing Candidate
( long "candidate"
<> help "Upload as a package candidate."
uploadOptsParser = UploadOpts
<$> dirsToWorkWithParser
<*> documentationParser
<*> optional pvpBoundsOption
<*> ignoreCheckSwitch
<*> buildPackageOption
<*> tarDirParser
<*> uploadVariantParser
where
dirsToWorkWithParser = many (strArgument
( metavar "DIR"
<> completer dirCompleter
))
documentationParser = flag False True
( long "documentation"
<> short 'd'
<> help "Upload documentation."
)
ignoreCheckSwitch = switch
( long "ignore-check"
<> help "Do not check package for common mistakes."
)
buildPackageOption = boolFlags False
"test-tarball"
"building of the resulting tarball."
idm
tarDirParser = optional (strOption
( long "tar-dir"
<> help "If specified, copy all the tar to this directory."
))
uploadVariantParser = flag Publishing Candidate
( long "candidate"
<> help "Upload as, or for, a package candidate."
)
25 changes: 16 additions & 9 deletions src/Stack/SDist.hs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ module Stack.SDist
, getSDistTarball
, checkSDistTarball
, checkSDistTarball'
, readLocalPackage
) where

import qualified Codec.Archive.Tar as Tar
Expand Down Expand Up @@ -129,15 +130,15 @@ instance Exception SDistPrettyException
-- | Type representing command line options for @stack sdist@ command.
data SDistOpts = SDistOpts
{ sdoptsDirsToWorkWith :: [String]
-- ^ Directories to package
-- ^ Directories to package
, sdoptsPvpBounds :: Maybe PvpBounds
-- ^ PVP Bounds overrides
-- ^ PVP Bounds overrides
, sdoptsIgnoreCheck :: Bool
-- ^ Whether to ignore check of the package for common errors
-- ^ Whether to ignore check of the package for common errors
, sdoptsBuildTarball :: Bool
-- ^ Whether to build the tarball
-- ^ Whether to build the tarball
, sdoptsTarPath :: Maybe FilePath
-- ^ Where to copy the tarball
-- ^ Where to copy the tarball
}

-- | Function underlying the @stack sdist@ command.
Expand Down Expand Up @@ -193,7 +194,12 @@ getSDistTarball ::
-- ^ Override Config value
-> Path Abs Dir
-- ^ Path to local package
-> RIO env (FilePath, L.ByteString, Maybe (PackageIdentifier, L.ByteString))
-> RIO
env
( FilePath
, L.ByteString
, Maybe (PackageIdentifier, L.ByteString)
)
-- ^ Filename, tarball contents, and option Cabal file revision to upload
getSDistTarball mpvpBounds pkgDir = do
config <- view configL
Expand Down Expand Up @@ -243,7 +249,7 @@ getSDistTarball mpvpBounds pkgDir = do
-- prone and more predictable to read everything in at once, so that's what
-- we're doing for now:
let tarPath isDir fp =
case Tar.toTarPath isDir (forceUtf8Enc (pkgId FP.</> fp)) of
case Tar.toTarPath isDir (forceUtf8Enc (pkgIdName FP.</> fp)) of
Left e -> prettyThrowIO $ ToTarPathException e
Right tp -> pure tp
-- convert a String of proper characters to a String of bytes in UTF8
Expand All @@ -268,8 +274,9 @@ getSDistTarball mpvpBounds pkgDir = do
pure $ (Tar.fileEntry tp lbs) { Tar.entryTime = floor currTime }
| otherwise = packWith packFileEntry False fp
isCabalFp fp = toFilePath pkgDir FP.</> fp == toFilePath cabalfp
tarName = pkgId FP.<.> "tar.gz"
pkgId = packageIdentifierString (packageIdentifier (lpPackage lp))
tarName = pkgIdName FP.<.> "tar.gz"
pkgIdName = packageIdentifierString pkgId
pkgId = packageIdentifier (lpPackage lp)
dirEntries <- mapM packDir (dirsFromFiles files)
fileEntries <- mapM packFile files
mcabalFileRevision <- liftIO (readIORef cabalFileRevisionRef)
Expand Down
Loading

0 comments on commit fd8d69e

Please sign in to comment.