fbrnch-1.8: src/Cmd/Update.hs
module Cmd.Update
( updateSourcesCmd,
updateSourcesPkg
)
where
import Data.RPM.VerCmp
import Data.Version (parseVersion)
import Fedora.Krb (krbTicket)
import Safe (headMay, tailSafe)
import SimplePrompt (promptEnter, yesNoDefault)
import System.IO.Extra (withTempDir)
import Text.ParserCombinators.ReadP (readP_to_S)
import Branches
import Cmd.CompareTarballs
import Common
import Common.System
import Git
import InterleaveOutput (cmdSilent')
import Package
-- FIXME --no-prep to avoid overwriting ongoing build
-- FIXME don't bump release if already bumped
-- FIXME check EVR increased
-- FIXME if multiple sources might need to bump release
-- FIXME Haskell subpackages require release bump even with version bump
updateSourcesCmd :: Bool -> Bool -> (Maybe Branch,[String]) -> IO ()
updateSourcesCmd force allowHEAD (mbr,args) = do
(mver,pkgs) <-
case args of
[] -> return (Nothing,[])
(h:t) -> do
exists <- doesDirectoryExist h
if exists || not (isVersion h)
then return (Nothing, args)
else do
havespec <- isJust <$> maybeFindSpecfile
if null t && not havespec
then error' "not a pkg dir"
else return (Just h, t)
pkgGit <- isPkgGitSshRepo
let mgitops =
let dirty = if allowHEAD then dirtyGitHEAD else dirtyGitFetch
in if pkgGit
then dirty
else if null pkgs then Nothing else dirty
withPackagesMaybeBranch HeaderMay False mgitops (updateSourcesPkg force allowHEAD pkgGit mver) (mbr, pkgs)
where
isVersion = not . null . readP_to_S parseVersion
updateSourcesPkg :: Bool -> Bool -> Bool -> Maybe String -> Package
-> AnyBranch -> IO ()
updateSourcesPkg force allowHEAD distgit mver pkg br = do
when (distgit && br /= RelBranch Rawhide && isRelBranch br) $
promptEnter $ "Are you sure you want to update" +-+ show br +-+ "branch?! Press Enter to continue"
spec <- if allowHEAD
then findSpecfile
else localBranchSpecFile pkg br
curver <- pkgVersion spec
diff <- filter (not . ("@@ " `isPrefixOf`)) <$> gitLines "diff" ["-U0", "HEAD", spec]
let vdiff = filter (\v -> any (`isPrefixOf` v) ["-Version:","+Version:"]) diff
mnewrel = find ("+Release:" `isPrefixOf`) diff
when (length vdiff > 2) $
error' $ "diff contains complex multi-version changes:\n" ++ unlines vdiff
case mver of
Nothing -> do
putStrLn $ "current version:" +-+ curver
Just nver -> do
when (length vdiff == 2) $
error' $ "spec version already bumped to" +-+ curver
when (curver == nver) $
putStrLn $ "already new version" +-+ curver
let moldnewver =
case mver of
Just nver -> Just (curver,nver)
Nothing ->
case map extractFieldValue vdiff of
[old,new] -> Just (old,new)
_ -> Nothing
when (isJust mver) $
when (isJust moldnewver) $ do
let (oldver,newver) =
fromMaybe (error' "complex version change") moldnewver
-- FIXME take epoch into account
when (rpmVerCompare oldver newver == GT) $
putStrLn $ "current" +-+ oldver +-+ "is newer!"
putStrLn $ oldver +-+ "->\n" ++ newver
when (curver /= newver) $ do
specversions <- grep "^Version:" spec
case specversions of
[] -> error' "no Version field found"
[specver] ->
when ('%' `elem` specver) $
error' "Please edit complex 'Version' fields with macro(s) by hand"
_ -> error' "Please edit package with multiple versions by hand"
editSpecField "Version" newver spec
autorelease <- isAutoRelease spec
if autorelease
then do
autoreset <- autoReleaseReset spec
when autoreset $
editSpecField "Release" "%autorelease" spec
-- FIXME if multiple versions need to bump release
else editSpecField "Release" "0%{?dist}" spec
-- FIXME should be sure sources exists for distgit
whenM (doesFileExist "sources") $
cmd_ "sed" ["-i", "/" ++ unPackage pkg ++ "-" ++ oldver ++ "./d", "sources"]
when distgit $ do
-- FIXME forM_
sources <- map sourceFieldFile <$> cmdLines "spectool" ["-S", spec]
existing <- filterM doesFileExist sources
unless (existing == sources) $ do
fedpkg_ "sources" []
unless force $
-- FIXME only if not all exist
cmd_ "spectool" ["-g", "-S", spec]
patches <- map sourceFieldFile <$> cmdLines "spectool" ["-P", spec]
forM_ patches $ \patch -> do
unlessM (doesFileExist patch) $
cmd_ "spectool" ["-g", "-P", spec]
git_ "add" [patch]
let (archives,textsources) = partition isArchiveFile sources
when force $ do
forM_ archives removeFile
cmd_ "spectool" ["-g", "-S", spec]
krbTicket
fedpkg_ "new-sources" archives
unless (null textsources) $
git_ "add" textsources
whenJust moldnewver $ \(_old,newver) -> do
whenM (yesNoDefault False "Do you want to diff the sources") $
compareTarballsCmd Nothing Nothing Nothing
versions <- changelogVersions spec
let missing =
case versions of
[] -> True
(h:_) -> not $ (newver ++ "-") `isPrefixOf` h
when missing $ do
-- FIXME newver may contain macros!
newversion <- pkgVersion spec
cmd_ "rpmdev-bumpspec" ["-c", "Update to" +-+ newversion, spec]
newrelease <- cmd "rpmspec" ["-q", "--srpm", "--undefine=dist", "--qf", "%{release}", spec]
-- revert release if was already bumped
whenJust (extractFieldValue <$> mnewrel) $ \newrel -> do
editSpecField "Release" newrel spec
cmd_ "sed" ["-i", "s/> -" +-+ newversion ++ '-' : newrelease ++ "/> -" +-+ newversion ++ '-' : replace "%{?dist}" "" newrel ++ "/" , spec]
git_ "commit" ["-a", "-m", "Update to" +-+ newversion]
putStr "Prepping... "
sourcediropt <- sourceDirCwdOpt
withTempDir $ \tempdir -> do
cwd <- getCurrentDirectory
withCurrentDirectory tempdir $ do
cmdSilent' "rpmbuild" $ "-bp" : sourcediropt ++ ["--nodeps", cwd </> spec]
putStrLn "done"
-- FIXME git amend (if previous commit was update)
changelogVersions :: FilePath -> IO [String]
changelogVersions spec = do
ns <- cmdLines "rpmspec" ["-q", "--srpm", "--qf", "%{changelogname}", spec]
return $ map (removePrefix "- " . dropWhile (/= '-')) ns
-- eg "?Release: 0.2%{?dist}"
extractFieldValue :: String -> String
extractFieldValue vs =
case headMay . tailSafe . words $ vs of
Just h -> h
Nothing -> error' $ "no field value:" +-+ vs