dl-fedora 2.0.1 → 2.1
raw patch · 5 files changed
+113/−77 lines, 5 filesdep −ansi-wl-pprint
Dependencies removed: ansi-wl-pprint
Files
- CHANGELOG.md +9/−0
- README.md +17/−15
- dl-fedora.cabal +1/−2
- src/Main.hs +74/−50
- test/tests.hs +12/−10
CHANGELOG.md view
@@ -1,5 +1,14 @@ # Changelog +## 2.1 (2025-08-30)+- unbreak bash-completion by reading rawhide and current release versions later+- add --qemu option to specify how to run iso (overrides $DLFEDORA_QEMU)+- help: print releases after editions+- only try http directory twice+- warn and rename if checksum filesize changed and small locally (unsigned)+- add Cosmic to liveRespin map+- MATE missing from F43+ and no MiracleWM respin+ ## 2.0.1 (2025-03-11) - 'stage' and 'test' releases also need to follow Kiwi editions
README.md view
@@ -12,17 +12,18 @@ `dl-fedora rawhide` : downloads the latest Fedora Rawhide Workstation Live iso -`dl-fedora 42 silverblue` : downloads the Fedora Silverblue iso+`dl-fedora 43 silverblue` : downloads the Fedora Silverblue iso `dl-fedora respin kde` : downloads the latest KDE Live respin -`dl-fedora 41 --list` : list editions for version+`dl-fedora 42 --list` : list editions for version -`dl-fedora 42 kde workstation` : download both KDE and Workstation editions+`dl-fedora 43 kde workstation` : download both KDE and Workstation editions -`dl-fedora 41 server --arch aarch64` : will download the Server iso for armv8+`dl-fedora 42 server --arch aarch64` : will download the Server iso for armv8 -`dl-fedora --run 42` : will download Fedora Workstation and boot the Live image with qemu-kvm.+`dl-fedora --run 43` : will download Fedora Workstation and boot the Live image with qemu-kvm.+(Set `DLFEDORA_QEMU` or `--qemu` to specify a command or script to run instead of the default "qemu-kvm") `dl-fedora --check respin` : checks if there is a newer respin iso image available.@@ -72,29 +73,28 @@ `$ dl-fedora --version` ```-2.0.1+2.1 ``` `$ dl-fedora --help` ``` Fedora iso downloader -Usage: dl-fedora [--version] [-g|--gpg-keys] [--no-checksum | --checksum] - [--debug] [-T|--no-http-timeout] - [(-c|--check) | (-l|--local) | --list | (-R|--replace)] - [-d|--dir DIRECTORY] [-n|--dry-run] [-r|--run] - [(-L|--latest) | --dl | (-k|--koji) | (-m|--mirror URL)] - [--dvd] [--cs-devel | --cs-test | --cs-production] +Usage: dl-fedora [--version] [-g|--gpg-keys] [--no-checksum | --checksum]+ [--debug] [-T|--no-http-timeout]+ [(-c|--check) | (-l|--local) | --list | (-R|--replace)]+ [-d|--dir DIRECTORY] [-n|--dry-run] [-r|--run] [-q|--qemu QEMU]+ [(-L|--latest) | --dl | (-k|--koji) | (-m|--mirror URL)]+ [--dvd] [--cs-devel | --cs-test | --cs-production] [--alt-cs-extra-edition ('MAX'|'MIN')] [-a|--arch ARCH] RELEASE [--all-desktops | --all-spins | --all-editions | [-x|--exclude] [EDITION...]] Tool for downloading Fedora iso file images.- RELEASE = release number, respin, rawhide, test (Beta), stage (RC), eln, c9s, c10s, c9s-live EDITION = {cloud,container,everything,kde,server,workstation,budgie,cinnamon, cosmic,i3,kdemobile,lxde,lxqt,mate,miracle,soas,sway,xfce, silverblue,kinoite,onyx,sericea,iot} [default: workstation]-+ RELEASE = release number, respin, rawhide, test (Beta), stage (RC), eln, c9s, c10s, c9s-live See <https://github.com/juhp/dl-fedora/#readme> Available options:@@ -113,6 +113,8 @@ -d,--dir DIRECTORY Download directory [default: ~/Downloads/iso] -n,--dry-run Don't actually download anything -r,--run Boot image in QEMU+ -q,--qemu QEMU specify QEMU command for --run (overrides+ $DLFEDORA_QEMU, defaults to qemu-kvm) -L,--latest Get latest image either from mirror or dl.fp.o if newer --dl Use dl.fedoraproject.org (dl.fp.o)@@ -143,4 +145,4 @@ ## Contribution dl-fedora is distributed under the GPL license version 3 or later. -Please report issues or pull requests at <https://github.com/juhp/dl-fedora>.+Please report issues or contribute at <https://github.com/juhp/dl-fedora>.
dl-fedora.cabal view
@@ -1,6 +1,6 @@ cabal-version: 1.18 name: dl-fedora-version: 2.0.1+version: 2.1 synopsis: Fedora image download tool description: Tool to download Fedora and Centos Stream iso and image files.@@ -31,7 +31,6 @@ DownloadDir build-depends: base < 5,- ansi-wl-pprint, bytestring, directory >= 1.2.5, extra,
src/Main.hs view
@@ -16,6 +16,7 @@ import qualified Data.ByteString.Char8 as B import Data.Char (isAlphaNum, isDigit) import Data.List.Extra+import Data.List.NonEmpty (NonEmpty(..), nonEmpty) import Data.Ord (comparing, Down(Down)) import Data.Maybe import qualified Data.Text as T@@ -27,11 +28,8 @@ import Network.HTTP.Client.TLS import Network.HTTP.Directory import Numeric.Natural- import Options.Applicative (fullDesc, header, progDescDoc)--import Paths_dl_fedora (version)-+import qualified Options.Applicative.Help.Pretty as P import SimpleCmd (cmd, cmd_, cmdBool, error', grep_, logMsg, pipe_, pipeBool, pipeFile_, warning, (+-+),@@ -49,6 +47,7 @@ listDirectory, pathIsSymbolicLink, removeFile, renameFile, setCurrentDirectory, withCurrentDirectory, writable)+import System.Environment (lookupEnv) import System.FilePath (dropFileName, isAbsolute, isRelative, makeRelative, joinPath, takeExtension, takeFileName, (</>), (<.>)) import System.Posix.Files (createSymbolicLink, fileSize, getFileStatus,@@ -59,9 +58,9 @@ import qualified Text.ParserCombinators.ReadP as R import qualified Text.ParserCombinators.ReadPrec as RP import Text.Regex.Posix-import qualified Text.PrettyPrint.ANSI.Leijen as P import DownloadDir+import Paths_dl_fedora (version) data FedoraEdition = Cloud | Container@@ -138,7 +137,7 @@ case rel of Rawhide -> allSpins rawhide current $ Fedora rawhide Fedora r -> fedoraSpins rel \\ missingEditions r- FedoraRespin -> delete KDEMobile $ allSpins rawhide current $ Fedora current+ FedoraRespin -> allSpins rawhide current (Fedora current) \\ [KDEMobile, Miracle] FedoraTest -> allSpins rawhide current $ Fedora current -- FIXME use fedora-releases FedoraStage -> allSpins rawhide current $ Fedora (current + 1) -- FIXME use fedora-releases CS 9 True -> [Cinnamon, KDE, MATE, Xfce] -- FIXME missing MAX, MIN@@ -162,7 +161,7 @@ missingEditions :: Natural -> [FedoraEdition] missingEditions r = case compare r 41 of- GT -> [IoT]+ GT -> IoT : [MATE | r >= 43] EQ -> [COSMIC] LT -> [COSMIC, KDEMobile, Miracle] @@ -244,22 +243,21 @@ data Mode = Check | Local | List | Download Bool -- replace deriving Eq +-- FIXME add --editions+-- FIXME add --releases main :: IO () main = do let pdoc = Just $ P.vcat- [ P.text "Tool for downloading Fedora iso file images.",- P.text ("RELEASE = " <> intercalate ", " ["release number", "respin", "rawhide", "test (Beta)", "stage (RC)", "eln", "c9s", "c10s", "c9s-live"]),- P.text "EDITION = " <> P.lbrace <> P.align (P.fillCat (P.punctuate P.comma (map (P.text . lowerEdition) [(minBound :: FedoraEdition)..maxBound])) <> P.rbrace) <> P.text " [default: workstation]" ,- P.text "",- P.text "See <https://github.com/juhp/dl-fedora/#readme>"+ [ P.pretty "Tool for downloading Fedora iso file images.",+ P.pretty "EDITION = " <> P.lbrace <> P.align (P.fillCat (P.punctuate P.comma (map (P.pretty . lowerEdition) [(minBound :: FedoraEdition)..maxBound])) <> P.rbrace) <> P.pretty " [default: workstation]" ,+ P.pretty ("RELEASE = " <> intercalate ", " ["release number", "respin", "rawhide", "test (Beta)", "stage (RC)", "eln", "c9s", "c10s", "c9s-live"]),+ P.pretty "See <https://github.com/juhp/dl-fedora/#readme>" ] sysarch <- readArch <$> cmd "rpm" ["--eval", "%{_arch}"]- rawhideVersion <- getRawhideVersion- currentRelease <- getCurrentFedoraVersion home <- getHomeDirectory defaultDir <- checkDefaultIsoDir simpleCmdArgsWithMods (Just version) (fullDesc <> header "Fedora iso downloader" <> progDescDoc pdoc) $- program rawhideVersion+ program <$> switchWith 'g' "gpg-keys" "Import Fedora GPG keys for verifying checksum file" <*> checksumOpts <*> switchLongWith "debug" "Debug output"@@ -271,6 +269,7 @@ <*> strOptionalWith 'd' "dir" "DIRECTORY" ("Download directory [default:" +-+ prettyDir home defaultDir ++ "]") defaultDir <*> switchWith 'n' "dry-run" "Don't actually download anything" <*> switchWith 'r' "run" "Boot image in QEMU"+ <*> optional (strOptionWith 'q' "qemu" "QEMU" "specify QEMU command for --run (overrides $DLFEDORA_QEMU, defaults to qemu-kvm)") <*> mirrorOpt <*> switchLongWith "dvd" "Download dvd iso instead of boot netinst (for Server, eln, centos)" <*> optional (flagLongWith' CSDevelopment "cs-devel" "Use centos-stream development compose" <|>@@ -278,7 +277,7 @@ flagLongWith' CSProduction "cs-production" "Use centos-stream production compose (default is mirror.stream.centos.org)") <*> optional (strOptionLongWith "alt-cs-extra-edition" "('MAX'|'MIN')" "Centos Stream Alternative Live Spin editions (MAX,MIN)") <*> (optionWith (eitherReader eitherArch) 'a' "arch" "ARCH" ("Specify arch [default:" +-+ showArch sysarch ++ "]") <|> pure sysarch)- <*> (readRelease rawhideVersion currentRelease <$> strArg "RELEASE")+ <*> strArg "RELEASE" <*> (flagLongWith' AllDesktops "all-desktops" "Get all Fedora desktops" <|> flagLongWith' AllSpins "all-spins" "Get all Fedora Spins" <|> flagLongWith' AllEditions "all-editions" "Get all Fedora editions" <|>@@ -303,10 +302,14 @@ primarySize :: Maybe Integer, primaryTime :: Maybe UTCTime} -program :: Natural -> Bool -> CheckSum -> Bool -> Bool -> Mode -> FilePath- -> Bool -> Bool -> Mirror -> Bool -> Maybe CentosChannel- -> Maybe String -> Arch -> Release -> RequestEditions -> IO ()-program rawhide gpg checksum debug notimeout mode dlDir dryrun run mirror dvdnet mchannel mcsedition arch tgtrel reqeditions = do+program :: Bool -> CheckSum -> Bool -> Bool -> Mode -> FilePath+ -> Bool -> Bool -> Maybe String -> Mirror -> Bool+ -> Maybe CentosChannel -> Maybe String -> Arch -> String+ -> RequestEditions -> IO ()+program gpg checksum debug notimeout mode dlDir dryrun run mqemu mirror dvdnet mchannel mcsedition arch tgtrelstr reqeditions = do+ rawhide <- getRawhideVersion+ currentRelease <- getCurrentFedoraVersion+ let tgtrel = readRelease rawhide currentRelease tgtrelstr when (isJust mchannel && not (isCentosStream tgtrel)) $ error' "channels are only for centos-stream" let mirrorUrl =@@ -349,7 +352,7 @@ _ -> error' "--alt-cs-extra-edition is only for CS Alt Live spins" current <- getCurrentFedoraVersion successes <-- mapM (runProgramEdition mgr mirrorUrl showdestdir gpg checksum debug mode dryrun run mirror dvdnet mchannel mcsedition arch tgtrel reqeditions) $+ mapM (runProgramEdition mgr mirrorUrl showdestdir gpg checksum debug mode dryrun run mqemu mirror dvdnet mchannel mcsedition arch tgtrel reqeditions) $ if mode == List then [Workstation] else@@ -392,10 +395,10 @@ _ -> True runProgramEdition :: Manager -> URL -> String -> Bool -> CheckSum -> Bool- -> Mode -> Bool -> Bool -> Mirror -> Bool- -> Maybe CentosChannel -> Maybe String -> Arch -> Release- -> RequestEditions -> FedoraEdition -> IO Bool-runProgramEdition mgr mirrorUrl showdestdir gpg checksum debug mode dryrun run mirror dvdnet mchannel mcsedition arch tgtrel reqeditions edition =+ -> Mode -> Bool -> Bool -> Maybe FilePath -> Mirror -> Bool+ -> Maybe CentosChannel -> Maybe String -> Arch+ -> Release -> RequestEditions -> FedoraEdition -> IO Bool+runProgramEdition mgr mirrorUrl showdestdir gpg checksum debug mode dryrun run mqemu mirror dvdnet mchannel mcsedition arch tgtrel reqeditions edition = case mode of Check -> do eres <- findURL True@@ -427,8 +430,7 @@ mtarget <- derefSymlink symlink whenJust mtarget $ \target -> do putStrLn $ "Local:" +-+ target- when run $- bootImage dryrun target showdestdir+ when run $ bootImage dryrun target showdestdir mqemu return True List -> do rawhide <- getRawhideVersion@@ -457,7 +459,7 @@ unless dryrun $ do let localfile = takeFileName fileurl updateSymlink localfile symlink removeold- when run $ bootImage dryrun localfile showdestdir+ when run $ bootImage dryrun localfile showdestdir mqemu return True where findURL :: Bool@@ -527,9 +529,9 @@ let url = top +/+ path when debug $ do print url- redirs <- retry 3 $ httpRedirects mgr $ replace "https:" "http:" url- print redirs- ls <- retry 3 $ httpDirectory mgr url+ -- force redirect+ httpRedirects mgr (replace "https:" "http:" url) >>= print+ ls <- retry 2 $ httpDirectory mgr url return (url, ls) findMirror primeUrl path file = do@@ -802,8 +804,15 @@ (primeSize,primeTime) <- retry 3 $ httpFileSizeTime mgr url when debug $ print (primeSize,primeTime,url) ok <- checkLocalFileSize filesize checksumfile primeSize primeTime True- unless ok $ error' $ "Checksum file filesize mismatch for " ++ checksumfile- return ok+ if ok+ then return True+ else+ if filesize < 900+ then do+ warning $ "Renaming unsigned checksum file" +-+ checksumfile+ renameFile checksumfile $ checksumfile <.> "old"+ return False+ else error' $ "Checksum file filesize mismatch for " ++ checksumfile checkForFedoraKeys :: Natural -> IO Bool checkForFedoraKeys n =@@ -867,7 +876,7 @@ then return Nothing else do tz <- getCurrentTimeZone- putStrLn $ unwords ["downloading", filename, renderTime tz mtime, "to", showdestdir]+ putStrLn $ unwords ["downloading", filename, renderTime tz mtime, "under", showdestdir] doCurl return (Just True) where@@ -897,25 +906,40 @@ liveRespin :: FedoraEdition -> String liveRespin Budgie = "Budgie"+liveRespin COSMIC = "COSMIC" liveRespin I3 = "i3" liveRespin Miracle = "MiracleWM" liveRespin e = take 4 . upper . showEdition FedoraRespin $ e -bootImage :: Bool -> FilePath -> String -> IO ()-bootImage dryrun img showdir = do+bootImage :: Bool -> FilePath -> String -> Maybe String -> IO ()+bootImage dryrun img showdir mqemu = do let fileopts = case takeExtension img of ".iso" -> ["-boot", "d", "-cdrom"] _ -> []- mQemu <- findExecutable "qemu-kvm"- case mQemu of- Just qemu -> do- let args = ["-m", "4096", "-rtc", "base=localtime", "-cpu", "host"] ++ fileopts- -- replace with showCommandForUser or cmdN when updated- putStrLn . unwords $ qemu : map translateInternal (args ++ [showdir </> img])- unless dryrun $- cmd_ qemu (args ++ [img])- Nothing -> error' "Need qemu to run image"+ qemucmd <-+ case mqemu of+ Just q -> return q+ Nothing -> do+ menv <- lookupEnv "DLFEDORA_QEMU"+ return $ fromMaybe "qemu-kvm" menv+ (c :| args) <-+ case nonEmpty (words qemucmd) of+ Nothing -> error' "qemu command cannot be empty"+ Just (q:|qs) -> do+ mQemu <- findExecutable q+ case mQemu of+ Nothing -> error' $ "No such program:" +-+ q+ Just qemu ->+ return $+ qemu :|+ if null qs+ then ["-m", "4096", "-rtc", "base=localtime", "-cpu", "host"] ++ fileopts+ else qs+ -- replace with showCommandForUser or cmdN when updated+ putStrLn . unwords $ c : args ++ [translateInternal (showdir </> img)]+ unless dryrun $+ cmd_ c (args ++ [img]) -- from process System.Process.Posix translateInternal :: String -> String@@ -938,11 +962,11 @@ #if !MIN_VERSION_http_directory(0,1,9) infixr 5 +/+ (+/+) :: String -> String -> String-"" +/+ s = s-s +/+ "" = s-s +/+ t | last s == '/' = init s +/+ t- | head t == '/' = s +/+ tail t-s +/+ t = s ++ "/" ++ t+s +/+ t =+ case (s,t) of+ ("",_) -> t+ (_,"") -> s+ (_,_) -> dropWhileEnd (== '/') s ++ '/' : dropWhile (== '/') t #endif -- derived from fedora-repoquery Types
test/tests.hs view
@@ -44,24 +44,26 @@ ,["-T", "-n", "c10s-live", "--all-editions"] ] -mkFedEdition :: String -> [String]-mkFedEdition ver =+mkFedEdition :: Natural -> [String]+mkFedEdition = mkFedEdition' . show++mkFedEdition' :: String -> [String]+mkFedEdition' ver = ["--dl", "-T", "-n", ver, "--all-editions"] allFedoraEditions :: Natural -> Natural -> [[String]] allFedoraEditions oldest rawhide =- map (mkFedEdition . show) [oldest..(rawhide-1)]- ++- [mkFedEdition "stage"]- ++- -- currently MATE is broken in Rawhide- [["--dl", "-T", "-n", show rawhide, "--exclude", "mate"]]+ map mkFedEdition [oldest..(rawhide-1)]+ -- currently empty+ -- ++ [mkFedEdition' "stage"]+ -- use --exclude for any missing+ ++ [mkFedEdition rawhide] allEditions :: Natural -> [String] allEditions 9 = allEditions 10 ++ ["cinnamon", "mate", "xfce"] allEditions 10 = ["workstation", "kde", "max", "min"]-allEditions rel = ["cloud","container","everything","server","workstation","budgie","cinnamon","i3","kde","lxde","lxqt","mate","soas","sway","xfce","silverblue","kinoite","onyx","sericea"] ++- ["cosmic" | rel >= 42] ++ ["kdemobile" | rel >= 41] ++ ["miracle" | rel >= 41] ++ ["iot" | rel < 42]+allEditions rel = ["cloud","container","everything","server","workstation","budgie","cinnamon","i3","kde","lxde","lxqt","soas","sway","xfce","silverblue","kinoite","onyx","sericea"] +++ ["cosmic" | rel >= 42] ++ ["kdemobile" | rel >= 41] ++ ["miracle" | rel >= 41] ++ ["iot" | rel < 42] ++ ["mate" | rel < 43] listEditions :: Natural -> IO () listEditions n = do