2014-06-18 19:21:29 +00:00
|
|
|
{- Downloads git-annex autobuilds and installs them into the git-annex
|
|
|
|
- repository in ~/lib/downloads that is used to distribute git-annex
|
|
|
|
- releases.
|
|
|
|
-
|
|
|
|
- Generates info files, containing the version (of the corresponding file
|
|
|
|
- from the autobuild).
|
2014-04-21 15:24:34 +00:00
|
|
|
-
|
2019-09-12 23:02:59 +00:00
|
|
|
- Builds standalone rpms from the standalone tarballs, and populates
|
2020-12-25 20:32:03 +00:00
|
|
|
- a rpm package repository with them using the createrepo_c program.
|
2019-09-12 23:02:59 +00:00
|
|
|
-
|
2014-04-21 15:24:34 +00:00
|
|
|
- Also gpg signs the files.
|
|
|
|
-}
|
2013-11-22 16:21:53 +00:00
|
|
|
|
2016-01-20 20:36:33 +00:00
|
|
|
import Annex.Common
|
2013-11-22 16:21:53 +00:00
|
|
|
import Types.Distribution
|
2015-04-20 20:09:24 +00:00
|
|
|
import Build.Version (getChangelogVersion, Version)
|
2013-11-22 16:21:53 +00:00
|
|
|
import Utility.UserInfo
|
2014-06-18 19:21:29 +00:00
|
|
|
import Utility.Url
|
2018-01-15 16:18:00 +00:00
|
|
|
import Utility.Tmp.Dir
|
2018-04-10 00:22:46 +00:00
|
|
|
import Utility.Metered
|
2013-11-22 16:21:53 +00:00
|
|
|
import qualified Git.Construct
|
|
|
|
import qualified Annex
|
|
|
|
import Annex.Content
|
2016-01-14 19:55:37 +00:00
|
|
|
import Annex.WorkTree
|
2013-11-22 16:21:53 +00:00
|
|
|
import Git.Command
|
2020-11-27 17:02:43 +00:00
|
|
|
import qualified Utility.RawFilePath as R
|
2013-11-22 16:21:53 +00:00
|
|
|
|
|
|
|
import Data.Time.Clock
|
2014-06-18 20:11:20 +00:00
|
|
|
import Data.Char
|
2019-11-15 02:25:06 +00:00
|
|
|
import Data.Either
|
2015-01-13 16:43:22 +00:00
|
|
|
import System.Posix.Directory
|
2013-11-22 16:21:53 +00:00
|
|
|
|
2014-04-21 15:24:34 +00:00
|
|
|
-- git-annex distribution signing key (for Joey Hess)
|
|
|
|
signingKey :: String
|
|
|
|
signingKey = "89C809CB"
|
|
|
|
|
2014-06-18 19:21:29 +00:00
|
|
|
-- URL to an autobuilt git-annex file, and the place to install
|
|
|
|
-- it in the repository.
|
|
|
|
autobuilds :: [(URLString, FilePath)]
|
|
|
|
autobuilds =
|
2018-10-11 17:22:02 +00:00
|
|
|
(map linuxarch ["i386", "amd64", "armel", "arm64", "i386-ancient"]) ++
|
2014-11-11 20:18:51 +00:00
|
|
|
[ (autobuild "x86_64-apple-yosemite/git-annex.dmg", "git-annex/OSX/current/10.10_Yosemite/git-annex.dmg")
|
2014-06-19 18:21:34 +00:00
|
|
|
, (autobuild "windows/git-annex-installer.exe", "git-annex/windows/current/git-annex-installer.exe")
|
2014-06-18 19:21:29 +00:00
|
|
|
]
|
|
|
|
where
|
|
|
|
linuxarch a =
|
2014-06-19 18:21:34 +00:00
|
|
|
( autobuild (a ++ "/git-annex-standalone-" ++ a ++ ".tar.gz")
|
2014-06-18 19:21:29 +00:00
|
|
|
, "git-annex/linux/current/git-annex-standalone-" ++ a ++ ".tar.gz"
|
|
|
|
)
|
2014-07-07 18:30:38 +00:00
|
|
|
autobuild f = "https://downloads.kitenet.net/git-annex/autobuild/" ++ f
|
2014-06-18 19:21:29 +00:00
|
|
|
|
2019-09-12 23:02:59 +00:00
|
|
|
-- Names of architectures in standalone tarballs and the corresponding
|
|
|
|
-- rpm architecture.
|
|
|
|
tarrpmarches :: [(String, String)]
|
|
|
|
tarrpmarches =
|
|
|
|
[ ("i386", "i386")
|
|
|
|
, ("amd64", "x86_64")
|
|
|
|
, ("arm64", "aarch64")
|
|
|
|
]
|
|
|
|
|
2014-06-18 19:21:29 +00:00
|
|
|
main :: IO ()
|
2013-11-22 16:21:53 +00:00
|
|
|
main = do
|
2016-12-24 18:46:31 +00:00
|
|
|
useFileSystemEncoding
|
2019-09-12 23:02:59 +00:00
|
|
|
version <- getChangelogVersion
|
2014-06-18 19:21:29 +00:00
|
|
|
repodir <- getRepoDir
|
2019-09-12 23:02:59 +00:00
|
|
|
topdir <- getCurrentDirectory
|
2015-01-13 16:43:22 +00:00
|
|
|
changeWorkingDirectory repodir
|
2014-06-18 19:21:29 +00:00
|
|
|
updated <- catMaybes <$> mapM (getbuild repodir) autobuilds
|
2020-11-16 13:56:03 +00:00
|
|
|
state <- Annex.new =<< Git.Construct.fromPath (toRawFilePath ".")
|
2020-03-30 19:13:16 +00:00
|
|
|
ood <- Annex.eval state $ do
|
2019-09-12 23:02:59 +00:00
|
|
|
buildrpms topdir updated
|
|
|
|
makeinfos updated version
|
2020-03-04 16:35:20 +00:00
|
|
|
syncToArchiveOrg
|
2020-03-30 19:13:16 +00:00
|
|
|
unless (null ood) $
|
|
|
|
error $ "Some info files are out of date: " ++ show (map fst ood)
|
2014-06-18 19:21:29 +00:00
|
|
|
|
2016-03-07 19:54:27 +00:00
|
|
|
-- Download a build from the autobuilder, virus check it, and return its
|
|
|
|
-- version.
|
2014-06-18 19:21:29 +00:00
|
|
|
-- It's very important that the version matches the build, otherwise
|
|
|
|
-- auto-upgrades can loop reatedly. So, check build-version before
|
|
|
|
-- and after downloading the file.
|
|
|
|
getbuild :: FilePath -> (URLString, FilePath) -> IO (Maybe (FilePath, Version))
|
|
|
|
getbuild repodir (url, f) = do
|
|
|
|
bv1 <- getbv
|
|
|
|
let dest = repodir </> f
|
|
|
|
let tmp = dest ++ ".tmp"
|
2020-10-29 14:33:12 +00:00
|
|
|
removeWhenExistsWith removeFile tmp
|
2020-11-16 13:56:03 +00:00
|
|
|
createDirectoryIfMissing True (fromRawFilePath (parentDir (toRawFilePath dest)))
|
2014-06-18 19:44:16 +00:00
|
|
|
let oops s = do
|
2020-10-29 14:33:12 +00:00
|
|
|
removeWhenExistsWith removeFile tmp
|
2014-06-18 19:44:16 +00:00
|
|
|
putStrLn $ "*** " ++ s
|
|
|
|
return Nothing
|
2018-04-10 00:22:46 +00:00
|
|
|
uo <- defUrlOptions
|
2019-11-15 02:25:06 +00:00
|
|
|
ifM (isRight <$> download nullMeterUpdate url tmp uo)
|
2016-03-07 19:54:27 +00:00
|
|
|
( ifM (liftIO $ virusFree tmp)
|
|
|
|
( do
|
|
|
|
bv2 <- getbv
|
|
|
|
case bv2 of
|
|
|
|
Nothing -> oops $ "no build-version file for " ++ url
|
|
|
|
(Just v)
|
|
|
|
| bv2 == bv1 -> do
|
2020-10-29 14:33:12 +00:00
|
|
|
removeWhenExistsWith removeFile dest
|
2016-03-07 19:54:27 +00:00
|
|
|
renameFile tmp dest
|
|
|
|
-- remove git rev part of version
|
|
|
|
let v' = takeWhile (/= '-') v
|
|
|
|
return $ Just (f, v')
|
|
|
|
| otherwise -> oops $ "build version changed while downloading " ++ url ++ " " ++ show (bv1, bv2)
|
|
|
|
, oops $ "VIRUS detected in " ++ url
|
|
|
|
)
|
2014-06-18 19:44:16 +00:00
|
|
|
, oops $ "failed to download " ++ url
|
2014-06-18 19:21:29 +00:00
|
|
|
)
|
|
|
|
where
|
2014-06-18 20:24:46 +00:00
|
|
|
bvurl = takeDirectory url ++ "/build-version"
|
2014-06-18 19:21:29 +00:00
|
|
|
getbv = do
|
2014-06-18 20:24:46 +00:00
|
|
|
bv <- catchDefaultIO "" $ readProcess "curl" ["--silent", bvurl]
|
2014-06-18 20:11:20 +00:00
|
|
|
return $ if null bv || any (not . versionchar) bv then Nothing else Just bv
|
|
|
|
versionchar c = isAlphaNum c || c == '.' || c == '-'
|
2013-11-22 16:21:53 +00:00
|
|
|
|
2020-05-01 23:05:35 +00:00
|
|
|
makeinfos :: [(FilePath, Version)] -> Version -> Annex [([Char], Maybe GitAnnexDistribution)]
|
2015-01-13 16:43:22 +00:00
|
|
|
makeinfos updated version = do
|
2014-11-11 20:49:24 +00:00
|
|
|
mapM_ (\f -> inRepo $ runBool [Param "annex", Param "add", File f]) (map fst updated)
|
2014-02-21 16:12:56 +00:00
|
|
|
void $ inRepo $ runBool
|
|
|
|
[ Param "commit"
|
2014-02-27 16:20:53 +00:00
|
|
|
, Param "-a"
|
2015-04-06 22:56:38 +00:00
|
|
|
, Param ("-S" ++ signingKey)
|
2014-02-21 16:12:56 +00:00
|
|
|
, Param "-m"
|
|
|
|
, Param $ "publishing git-annex " ++ version
|
|
|
|
]
|
2013-11-22 16:21:53 +00:00
|
|
|
now <- liftIO getCurrentTime
|
2015-01-13 16:43:22 +00:00
|
|
|
liftIO $ putStrLn $ "building info files"
|
2014-06-18 19:21:29 +00:00
|
|
|
forM_ updated $ \(f, bv) -> do
|
2020-07-10 18:17:35 +00:00
|
|
|
v <- lookupKey (toRawFilePath f)
|
2013-11-22 16:21:53 +00:00
|
|
|
case v of
|
|
|
|
Nothing -> noop
|
2014-04-21 14:47:26 +00:00
|
|
|
Just k -> whenM (inAnnex k) $ do
|
2013-11-22 16:21:53 +00:00
|
|
|
liftIO $ putStrLn f
|
2015-01-13 16:43:22 +00:00
|
|
|
let infofile = f ++ ".info"
|
2017-02-24 22:51:57 +00:00
|
|
|
let d = GitAnnexDistribution
|
2014-06-18 20:34:28 +00:00
|
|
|
{ distributionUrl = mkUrl f
|
2019-12-18 18:37:59 +00:00
|
|
|
, distributionKey = fromKey id k
|
2014-06-18 19:21:29 +00:00
|
|
|
, distributionVersion = bv
|
2013-11-22 16:21:53 +00:00
|
|
|
, distributionReleasedate = now
|
2018-06-26 01:50:38 +00:00
|
|
|
, distributionUrgentUpgrade = Just "6.20180626"
|
2013-11-22 16:21:53 +00:00
|
|
|
}
|
2017-02-24 22:51:57 +00:00
|
|
|
liftIO $ writeFile infofile $ formatInfoFile d
|
2014-04-21 15:24:34 +00:00
|
|
|
void $ inRepo $ runBool [Param "add", File infofile]
|
|
|
|
signFile infofile
|
2015-01-13 16:43:22 +00:00
|
|
|
signFile f
|
2013-11-22 16:21:53 +00:00
|
|
|
void $ inRepo $ runBool
|
|
|
|
[ Param "commit"
|
2015-04-06 22:56:38 +00:00
|
|
|
, Param ("-S" ++ signingKey)
|
2015-04-06 22:38:34 +00:00
|
|
|
, Param "-m"
|
2014-02-21 16:12:56 +00:00
|
|
|
, Param $ "updated info files for git-annex " ++ version
|
2013-11-22 16:21:53 +00:00
|
|
|
]
|
2013-11-22 19:02:31 +00:00
|
|
|
void $ inRepo $ runBool
|
2013-11-25 18:14:45 +00:00
|
|
|
[ Param "annex"
|
2015-06-01 17:52:23 +00:00
|
|
|
, Param "move"
|
|
|
|
, Param "--to"
|
|
|
|
, Param "website"
|
2019-12-31 22:09:17 +00:00
|
|
|
, Param "--force"
|
2013-11-22 19:02:31 +00:00
|
|
|
]
|
|
|
|
void $ inRepo $ runBool
|
2013-11-25 18:14:45 +00:00
|
|
|
[ Param "annex"
|
2015-06-01 17:52:23 +00:00
|
|
|
, Param "sync"
|
2013-11-22 19:02:31 +00:00
|
|
|
]
|
2014-02-10 19:28:00 +00:00
|
|
|
|
2014-06-18 19:21:29 +00:00
|
|
|
-- Check for out of date info files.
|
2014-02-10 19:33:37 +00:00
|
|
|
infos <- liftIO $ filter (".info" `isSuffixOf`)
|
2015-01-13 16:43:22 +00:00
|
|
|
<$> dirContentsRecursive "git-annex"
|
2014-02-10 19:28:00 +00:00
|
|
|
ds <- liftIO $ forM infos (readish <$$> readFile)
|
|
|
|
let dis = zip infos ds
|
2015-01-13 16:43:22 +00:00
|
|
|
let ood = filter outofdate dis
|
2020-03-30 19:13:16 +00:00
|
|
|
return ood
|
2014-02-10 19:28:00 +00:00
|
|
|
where
|
2015-01-13 16:43:22 +00:00
|
|
|
outofdate (_, md) = case md of
|
2014-02-10 19:28:00 +00:00
|
|
|
Nothing -> True
|
|
|
|
Just d -> distributionVersion d /= version
|
2013-11-22 16:21:53 +00:00
|
|
|
|
|
|
|
getRepoDir :: IO FilePath
|
|
|
|
getRepoDir = do
|
|
|
|
home <- liftIO myHomeDir
|
|
|
|
return $ home </> "lib" </> "downloads"
|
|
|
|
|
2014-06-18 20:34:28 +00:00
|
|
|
mkUrl :: FilePath -> String
|
|
|
|
mkUrl f = "https://downloads.kitenet.net/" ++ f
|
2014-04-21 15:24:34 +00:00
|
|
|
|
|
|
|
signFile :: FilePath -> Annex ()
|
|
|
|
signFile f = do
|
|
|
|
void $ liftIO $ boolSystem "gpg"
|
|
|
|
[ Param "-a"
|
|
|
|
, Param $ "--default-key=" ++ signingKey
|
2014-04-21 15:56:06 +00:00
|
|
|
, Param "--detach-sign"
|
2014-04-21 15:24:34 +00:00
|
|
|
, File f
|
|
|
|
]
|
|
|
|
liftIO $ rename (f ++ ".asc") (f ++ ".sig")
|
|
|
|
void $ inRepo $ runBool [Param "add", File (f ++ ".sig")]
|
2016-03-07 19:54:27 +00:00
|
|
|
|
|
|
|
-- clamscan should handle unpacking archives, but did not in my
|
|
|
|
-- testing, so do it manually.
|
|
|
|
virusFree :: FilePath -> IO Bool
|
|
|
|
virusFree f
|
|
|
|
| ".tar.gz" `isSuffixOf` f = unpack $ \tmpdir ->
|
|
|
|
boolSystem "tar" [ Param "xf", File f, Param "-C", File tmpdir ]
|
|
|
|
| ".dmg" `isSuffixOf` f = unpack $ \tmpdir -> do
|
|
|
|
-- 7z can extract partitions from a dmg, and then
|
|
|
|
-- run on partitions can extract their files
|
|
|
|
unhfs tmpdir f
|
|
|
|
parts <- filter (".hfs" `isSuffixOf`) <$> getDirectoryContents tmpdir
|
|
|
|
forM_ parts $ unhfs tmpdir
|
|
|
|
return True
|
|
|
|
| otherwise = clamscan f
|
|
|
|
where
|
|
|
|
clamscan f' = boolSystem "clamscan"
|
|
|
|
[ Param "--no-summary"
|
|
|
|
, Param "-r"
|
|
|
|
, Param f'
|
|
|
|
]
|
|
|
|
unpack unpacker = withTmpDir "clamscan" $ \tmpdir -> do
|
|
|
|
unlessM (unpacker tmpdir) $
|
|
|
|
error $ "Failed to unpack " ++ f ++ " for virus scan"
|
|
|
|
clamscan tmpdir
|
|
|
|
unhfs dest f' = unlessM (boolSystem "7z" [ Param "x", Param ("-o" ++ dest), File f' ]) $
|
|
|
|
error $ "Failed extracting hfs " ++ f'
|
2019-09-13 16:00:16 +00:00
|
|
|
|
|
|
|
buildrpms :: FilePath -> [(FilePath, Version)] -> Annex ()
|
|
|
|
buildrpms topdir l = do
|
2019-12-18 18:32:13 +00:00
|
|
|
liftIO $ createDirectoryIfMissing True rpmrepo
|
|
|
|
oldrpms <- map (rpmrepo </>) . filter (".rpm" `isSuffixOf`)
|
2019-12-18 18:36:19 +00:00
|
|
|
<$> liftIO (getDirectoryContents rpmrepo)
|
2019-09-13 16:00:16 +00:00
|
|
|
forM_ tarrpmarches $ \(tararch, rpmarch) ->
|
2019-12-18 18:32:13 +00:00
|
|
|
forM_ (filter (isstandalonetarball tararch . fst) l) $ \(tarball, v) -> do
|
2020-11-27 17:02:43 +00:00
|
|
|
liftIO $ mapM_ (removeWhenExistsWith (R.removeLink . toRawFilePath))
|
|
|
|
(filter ((rpmarch ++ ".rpm") `isSuffixOf`) oldrpms)
|
2019-09-13 16:00:16 +00:00
|
|
|
void $ liftIO $ boolSystem script
|
|
|
|
[ Param rpmarch
|
|
|
|
, File tarball
|
|
|
|
, Param v
|
|
|
|
, File rpmrepo
|
|
|
|
]
|
2019-12-18 18:33:29 +00:00
|
|
|
void $ inRepo $ runBool [Param "annex", Param "get", File rpmrepo]
|
2020-12-25 20:32:03 +00:00
|
|
|
void $ liftIO $ boolSystem "createrepo_c" [File rpmrepo]
|
2019-09-13 16:00:16 +00:00
|
|
|
void $ inRepo $ runBool [Param "annex", Param "add", File rpmrepo]
|
|
|
|
where
|
|
|
|
isstandalonetarball tararch f =
|
|
|
|
("git-annex-standalone-" ++ tararch ++ ".tar.gz") `isSuffixOf` f
|
|
|
|
script = topdir </> "standalone" </> "rpm" </> "rpmbuild-from-standalone-tarball"
|
|
|
|
rpmrepo = "git-annex/linux/current/rpms"
|
2020-03-04 16:35:20 +00:00
|
|
|
|
|
|
|
-- My .mrconfig is configured to copy new files to archive.org,
|
|
|
|
-- and moves old versions of content to archive.org to free up space on my
|
|
|
|
-- server.
|
|
|
|
syncToArchiveOrg :: IO ()
|
|
|
|
syncToArchiveOrg = void $ boolSystem "mr"
|
|
|
|
[ Param "-d"
|
|
|
|
, File "/srv/web/downloads.kitenet.net"
|
|
|
|
, Param "update"
|
|
|
|
]
|