uploadAction :: UploadFlags -> [String] -> Action
uploadAction uploadFlags extraArgs globalFlags = do
  config <- loadConfig verbosity (globalConfigFile globalFlags)
  let uploadFlags' = savedUploadFlags config `mappend` uploadFlags
      globalFlags' = savedGlobalFlags config `mappend` globalFlags
      tarfiles     = extraArgs
  when (null tarfiles && not (fromFlag (uploadDoc uploadFlags'))) $
    die "the 'upload' command expects at least one .tar.gz archive."
  when (fromFlag (uploadCheck uploadFlags') && fromFlag (uploadDoc uploadFlags')) $
    die "--check and --doc cannot be used together."
  checkTarFiles extraArgs
  maybe_password <-
    case uploadPasswordCmd uploadFlags'
    of Flag (xs:xss) -> Just . Password <$>
                        getProgramInvocationOutput verbosity
                        (simpleProgramInvocation xs xss)
       _             -> pure $ flagToMaybe $ uploadPassword uploadFlags'
  transport <- configureTransport verbosity (flagToMaybe (globalHttpTransport globalFlags'))
  if fromFlag (uploadCheck uploadFlags')
  then do
    Upload.check transport verbosity tarfiles
  else if fromFlag (uploadDoc uploadFlags')
  then do
    when (length tarfiles > 1) $
     die "the 'upload' command can only upload documentation for one package at a time."
    tarfile <- maybe (generateDocTarball config) return $ listToMaybe tarfiles
    withGlobalRepos verbosity globalFlags' $ \globalRepos ->
      Upload.uploadDoc transport verbosity globalRepos
                    (flagToMaybe $ uploadUsername uploadFlags') maybe_password tarfile
  else do
    withGlobalRepos verbosity globalFlags' $ \globalRepos ->
      Upload.upload transport verbosity globalRepos
                  (flagToMaybe $ uploadUsername uploadFlags') maybe_password tarfiles

  where
    verbosity = fromFlag (uploadVerbosity uploadFlags)
    checkTarFiles tarfiles
      | not (null otherFiles)
      = die $ "the 'upload' command expects only .tar.gz archives: "
           ++ intercalate ", " otherFiles
      | otherwise = sequence_
                      [ do exists <- doesFileExist tarfile
                           unless exists $ die $ "file not found: " ++ tarfile
                      | tarfile <- tarfiles ]

      where otherFiles = filter (not . isTarGzFile) tarfiles
            isTarGzFile file = case splitExtension file of
              (file', ".gz") -> takeExtension file' == ".tar"
              _              -> False
    generateDocTarball config = do
      notice verbosity  "No documentation tarball specified. Building documentation tarball..."
      haddockAction (defaultHaddockFlags { haddockForHackage = Flag True }) [] globalFlags
      distPref <- findSavedDistPref config NoFlag
      pkg <- fmap LBI.localPkgDescr (getPersistBuildConfig distPref)
      return $ distPref </> display (packageId pkg) ++ "-docs" <.> "tar.gz"
uploadAction :: UploadFlags -> [String] -> Action
uploadAction uploadFlags extraArgs globalFlags = do
  config <- loadConfig verbosity (globalConfigFile globalFlags)
  let uploadFlags' = savedUploadFlags config `mappend` uploadFlags
      globalFlags' = savedGlobalFlags config `mappend` globalFlags
      tarfiles     = extraArgs
  when (null tarfiles && not (fromFlag (uploadDoc uploadFlags'))) $
    die "the 'upload' command expects at least one .tar.gz archive."
  when (fromFlag (uploadCheck uploadFlags') && fromFlag (uploadDoc uploadFlags')) $
    die "--check and --doc cannot be used together."
  checkTarFiles extraArgs
  maybe_password <-
    case uploadPasswordCmd uploadFlags'
    of Flag (xs:xss) -> Just . Password <$>
                        getProgramInvocationOutput verbosity
                        (simpleProgramInvocation xs xss)
       _             -> pure $ flagToMaybe $ uploadPassword uploadFlags'
  transport <- configureTransport verbosity (flagToMaybe (globalHttpTransport globalFlags'))
  if fromFlag (uploadCheck uploadFlags')
  then do
    Upload.check transport verbosity tarfiles
  else if fromFlag (uploadDoc uploadFlags')
  then do
    when (length tarfiles > 1) $
     die "the 'upload' command can only upload documentation for one package at a time."
    tarfile <- maybe (generateDocTarball config) return $ listToMaybe tarfiles
    withGlobalRepos verbosity globalFlags' $ \globalRepos ->
      Upload.uploadDoc transport verbosity globalRepos
                    (flagToMaybe $ uploadUsername uploadFlags') maybe_password tarfile
  else do
    withGlobalRepos verbosity globalFlags' $ \globalRepos ->
      Upload.upload transport verbosity globalRepos
                  (flagToMaybe $ uploadUsername uploadFlags') maybe_password tarfiles

  where
    verbosity = fromFlag (uploadVerbosity uploadFlags)
    checkTarFiles tarfiles
      | not (null otherFiles)
      = die $ "the 'upload' command expects only .tar.gz archives: "
           ++ intercalate ", " otherFiles
      | otherwise = sequence_
                      [ do exists <- doesFileExist tarfile
                           unless exists $ die $ "file not found: " ++ tarfile
                      | tarfile <- tarfiles ]

      where otherFiles = filter (not . isTarGzFile) tarfiles
            isTarGzFile file = case splitExtension file of
              (file', ".gz") -> takeExtension file' == ".tar"
              _              -> False
    generateDocTarball config = do
      notice verbosity  "No documentation tarball specified. Building documentation tarball..."
      haddockAction (defaultHaddockFlags { haddockForHackage = Flag True }) [] globalFlags
      distPref <- findSavedDistPref config NoFlag
      pkg <- fmap LBI.localPkgDescr (getPersistBuildConfig distPref)
      return $ distPref </> display (packageId pkg) ++ "-docs" <.> "tar.gz"
uploadAction uploadFlags extraArgs globalFlags = do
  config <- loadConfig verbosity (globalConfigFile globalFlags)
  let uploadFlags' = savedUploadFlags config `mappend` uploadFlags
      globalFlags' = savedGlobalFlags config `mappend` globalFlags
      tarfiles     = extraArgs
  when (null tarfiles && not (fromFlag (uploadDoc uploadFlags'))) $
    die "the 'upload' command expects at least one .tar.gz archive."
  when (fromFlag (uploadCheck uploadFlags') && fromFlag (uploadDoc uploadFlags')) $
    die "--check and --doc cannot be used together."
  checkTarFiles extraArgs
  maybe_password <-
    case uploadPasswordCmd uploadFlags'
    of Flag (xs:xss) -> Just . Password <$>
                        getProgramInvocationOutput verbosity
                        (simpleProgramInvocation xs xss)
       _             -> pure $ flagToMaybe $ uploadPassword uploadFlags'
  transport <- configureTransport verbosity (flagToMaybe (globalHttpTransport globalFlags'))
  if fromFlag (uploadCheck uploadFlags')
  then do
    Upload.check transport verbosity tarfiles
  else if fromFlag (uploadDoc uploadFlags')
  then do
    when (length tarfiles > 1) $
     die "the 'upload' command can only upload documentation for one package at a time."
    tarfile <- maybe (generateDocTarball config) return $ listToMaybe tarfiles
    withGlobalRepos verbosity globalFlags' $ \globalRepos ->
      Upload.uploadDoc transport verbosity globalRepos
                    (flagToMaybe $ uploadUsername uploadFlags') maybe_password tarfile
  else do
    withGlobalRepos verbosity globalFlags' $ \globalRepos ->
      Upload.upload transport verbosity globalRepos
                  (flagToMaybe $ uploadUsername uploadFlags') maybe_password tarfiles

  where
    verbosity = fromFlag (uploadVerbosity uploadFlags)
    checkTarFiles tarfiles
      | not (null otherFiles)
      = die $ "the 'upload' command expects only .tar.gz archives: "
           ++ intercalate ", " otherFiles
      | otherwise = sequence_
                      [ do exists <- doesFileExist tarfile
                           unless exists $ die $ "file not found: " ++ tarfile
                      | tarfile <- tarfiles ]

      where otherFiles = filter (not . isTarGzFile) tarfiles
            isTarGzFile file = case splitExtension file of
              (file', ".gz") -> takeExtension file' == ".tar"
              _              -> False
    generateDocTarball config = do
      notice verbosity  "No documentation tarball specified. Building documentation tarball..."
      haddockAction (defaultHaddockFlags { haddockForHackage = Flag True }) [] globalFlags
      distPref <- findSavedDistPref config NoFlag
      pkg <- fmap LBI.localPkgDescr (getPersistBuildConfig distPref)
      return $ distPref </> display (packageId pkg) ++ "-docs" <.> "tar.gz"