2012-12-14 19:52:44 +00:00
|
|
|
{- Makes standalone bundle.
|
|
|
|
-
|
2020-08-03 17:43:21 +00:00
|
|
|
- Copyright 2012-2020 Joey Hess <id@joeyh.name>
|
2012-12-14 19:52:44 +00:00
|
|
|
-
|
2019-03-13 19:48:14 +00:00
|
|
|
- Licensed under the GNU AGPL version 3 or higher.
|
2012-12-14 19:52:44 +00:00
|
|
|
-}
|
|
|
|
|
|
|
|
{-# LANGUAGE CPP #-}
|
2020-08-03 17:43:21 +00:00
|
|
|
{-# LANGUAGE LambdaCase #-}
|
2012-12-14 19:52:44 +00:00
|
|
|
|
2013-04-17 15:57:46 +00:00
|
|
|
module Main where
|
|
|
|
|
2020-08-03 17:43:21 +00:00
|
|
|
import System.Environment (getArgs)
|
2012-12-14 19:52:44 +00:00
|
|
|
import Control.Monad.IfElse
|
|
|
|
import System.FilePath
|
2019-10-17 15:01:41 +00:00
|
|
|
import System.Posix.Files
|
2012-12-14 19:52:44 +00:00
|
|
|
import Control.Monad
|
2019-10-17 16:41:02 +00:00
|
|
|
import qualified Data.ByteString.Lazy as L
|
2020-08-03 17:43:21 +00:00
|
|
|
import qualified Data.Map as M
|
2012-12-14 19:52:44 +00:00
|
|
|
|
|
|
|
import Utility.SafeCommand
|
2019-10-17 15:01:41 +00:00
|
|
|
import Utility.Process
|
2012-12-14 19:52:44 +00:00
|
|
|
import Utility.Path
|
2020-11-09 16:06:53 +00:00
|
|
|
import Utility.Path.AbsRel
|
2016-04-28 19:18:11 +00:00
|
|
|
import Utility.Directory
|
2020-08-03 17:43:21 +00:00
|
|
|
import Utility.Env
|
2020-11-09 16:06:53 +00:00
|
|
|
import Utility.FileSystemEncoding
|
2020-08-03 17:43:21 +00:00
|
|
|
import Build.BundledPrograms
|
|
|
|
#ifdef darwin_HOST_OS
|
2020-08-07 17:15:36 +00:00
|
|
|
import System.IO
|
2020-08-03 17:43:21 +00:00
|
|
|
import Build.OSXMkLibs (mklibs)
|
|
|
|
import Build.Version
|
|
|
|
import Utility.Split
|
|
|
|
#else
|
|
|
|
import Build.LinuxMkLibs (mklibs)
|
|
|
|
import Utility.FileMode
|
|
|
|
#endif
|
2012-12-14 19:52:44 +00:00
|
|
|
|
|
|
|
progDir :: FilePath -> FilePath
|
|
|
|
#ifdef darwin_HOST_OS
|
|
|
|
progDir topdir = topdir
|
|
|
|
#else
|
|
|
|
progDir topdir = topdir </> "bin"
|
|
|
|
#endif
|
|
|
|
|
2016-02-19 20:19:19 +00:00
|
|
|
extraProgDir :: FilePath -> FilePath
|
|
|
|
extraProgDir topdir = topdir </> "extra"
|
|
|
|
|
2013-04-22 17:33:29 +00:00
|
|
|
installProg :: FilePath -> FilePath -> IO (FilePath, FilePath)
|
2012-12-14 19:52:44 +00:00
|
|
|
installProg dir prog = searchPath prog >>= go
|
|
|
|
where
|
|
|
|
go Nothing = error $ "cannot find " ++ prog ++ " in PATH"
|
2013-04-22 17:33:29 +00:00
|
|
|
go (Just f) = do
|
|
|
|
let dest = dir </> takeFileName f
|
|
|
|
unlessM (boolSystem "install" [File f, File dest]) $
|
|
|
|
error $ "install failed for " ++ prog
|
|
|
|
return (dest, f)
|
2012-12-14 19:52:44 +00:00
|
|
|
|
2020-08-03 17:43:21 +00:00
|
|
|
installBundledPrograms :: FilePath -> IO (M.Map FilePath FilePath)
|
|
|
|
installBundledPrograms topdir = M.fromList . concat <$> mapM go
|
|
|
|
[ (progDir topdir, preferredBundledPrograms)
|
|
|
|
, (extraProgDir topdir, extraBundledPrograms)
|
|
|
|
]
|
|
|
|
where
|
|
|
|
go (dir, progs) = do
|
|
|
|
createDirectoryIfMissing True dir
|
|
|
|
forM progs $ installProg dir
|
|
|
|
|
2019-10-17 15:01:41 +00:00
|
|
|
installGitLibs :: FilePath -> IO ()
|
|
|
|
installGitLibs topdir = do
|
|
|
|
-- install git-core programs; these are run by the git command
|
|
|
|
createDirectoryIfMissing True gitcoredestdir
|
|
|
|
execpath <- getgitpath "exec-path"
|
|
|
|
cfs <- dirContents execpath
|
|
|
|
forM_ cfs $ \f -> do
|
2020-11-09 16:06:53 +00:00
|
|
|
destf <- ((gitcoredestdir </>) . fromRawFilePath)
|
|
|
|
<$> relPathDirToFile
|
|
|
|
(toRawFilePath execpath)
|
|
|
|
(toRawFilePath f)
|
2019-10-17 15:01:41 +00:00
|
|
|
createDirectoryIfMissing True (takeDirectory destf)
|
2019-10-17 15:55:51 +00:00
|
|
|
issymlink <- isSymbolicLink <$> getSymbolicLinkStatus f
|
2019-10-17 15:01:41 +00:00
|
|
|
if issymlink
|
|
|
|
then do
|
|
|
|
-- many git-core files may symlink to eg
|
2019-11-14 19:08:23 +00:00
|
|
|
-- ../../bin/git, which is located outside
|
|
|
|
-- the git-core directory. The target of
|
2019-11-14 20:15:42 +00:00
|
|
|
-- such links is installed into the progDir
|
|
|
|
-- (if not already there), and the links
|
|
|
|
-- repointed to it.
|
2019-11-14 19:08:23 +00:00
|
|
|
--
|
|
|
|
-- Other git-core files symlink to a file
|
|
|
|
-- beside them in the directory. Those
|
|
|
|
-- links can be copied as-is.
|
2019-10-17 15:01:41 +00:00
|
|
|
linktarget <- readSymbolicLink f
|
2019-11-14 19:08:23 +00:00
|
|
|
if takeFileName linktarget == linktarget
|
|
|
|
then cp f destf
|
|
|
|
else do
|
2019-11-14 20:34:13 +00:00
|
|
|
let linktarget' = progDir topdir </> takeFileName linktarget
|
2019-11-14 20:15:42 +00:00
|
|
|
unlessM (doesFileExist linktarget') $ do
|
|
|
|
createDirectoryIfMissing True (takeDirectory linktarget')
|
|
|
|
L.readFile f >>= L.writeFile linktarget'
|
2020-10-29 14:33:12 +00:00
|
|
|
removeWhenExistsWith removeLink destf
|
2020-11-09 16:06:53 +00:00
|
|
|
rellinktarget <- relPathDirToFile
|
|
|
|
(toRawFilePath (takeDirectory destf))
|
|
|
|
(toRawFilePath linktarget')
|
|
|
|
createSymbolicLink (fromRawFilePath rellinktarget) destf
|
2019-10-17 15:01:41 +00:00
|
|
|
else cp f destf
|
|
|
|
|
|
|
|
-- install git's template files
|
|
|
|
-- git does not have an option to get the path of these,
|
|
|
|
-- but they're architecture independent files, so are located
|
|
|
|
-- next to the --man-path, in eg /usr/share/git-core
|
|
|
|
manpath <- getgitpath "man-path"
|
|
|
|
let templatepath = manpath </> ".." </> "git-core" </> "templates"
|
|
|
|
tfs <- dirContents templatepath
|
|
|
|
forM_ tfs $ \f -> do
|
2020-11-09 16:06:53 +00:00
|
|
|
destf <- ((templatedestdir </>) . fromRawFilePath)
|
|
|
|
<$> relPathDirToFile
|
|
|
|
(toRawFilePath templatepath)
|
|
|
|
(toRawFilePath f)
|
2019-10-17 15:01:41 +00:00
|
|
|
createDirectoryIfMissing True (takeDirectory destf)
|
|
|
|
cp f destf
|
|
|
|
where
|
|
|
|
gitcoredestdir = topdir </> "git-core"
|
|
|
|
templatedestdir = topdir </> "templates"
|
|
|
|
|
|
|
|
getgitpath v = do
|
|
|
|
let opt = "--" ++ v
|
|
|
|
ls <- lines <$> readProcess "git" [opt]
|
|
|
|
case ls of
|
|
|
|
[] -> error $ "git " ++ opt ++ "did not output a location"
|
|
|
|
(p:_) -> return p
|
2020-08-03 17:43:21 +00:00
|
|
|
|
|
|
|
cp :: FilePath -> FilePath -> IO ()
|
|
|
|
cp src dest = do
|
2020-10-29 14:33:12 +00:00
|
|
|
removeWhenExistsWith removeLink dest
|
2020-08-03 17:43:21 +00:00
|
|
|
unlessM (boolSystem "cp" [Param "-a", File src, File dest]) $
|
|
|
|
error "cp failed"
|
|
|
|
|
|
|
|
installMagic :: FilePath -> IO ()
|
|
|
|
#ifdef darwin_HOST_OS
|
|
|
|
installMagic topdir = getEnv "OSX_MAGIC_FILE" >>= \case
|
2020-08-07 17:15:36 +00:00
|
|
|
Nothing -> hPutStrLn stderr "OSX_MAGIC_FILE not set; not including it"
|
2020-08-03 17:43:21 +00:00
|
|
|
Just f -> do
|
|
|
|
let mdir = topdir </> "magic"
|
|
|
|
createDirectoryIfMissing True mdir
|
2020-08-07 17:30:11 +00:00
|
|
|
unlessM (boolSystem "cp" [File f, File (mdir </> "magic.mgc")]) $
|
2020-08-03 17:43:21 +00:00
|
|
|
error "cp failed"
|
|
|
|
#else
|
|
|
|
installMagic topdir = do
|
|
|
|
let mdir = topdir </> "magic"
|
|
|
|
createDirectoryIfMissing True mdir
|
|
|
|
unlessM (boolSystem "cp" [File "/usr/share/file/magic.mgc", File (mdir </> "magic.mgc")]) $
|
|
|
|
error "cp failed"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
installLocales :: FilePath -> IO ()
|
|
|
|
#ifdef darwin_HOST_OS
|
|
|
|
installLocales _ = return ()
|
|
|
|
#else
|
|
|
|
installLocales topdir = cp "/usr/share/i18n" (topdir </> "i18n")
|
|
|
|
#endif
|
|
|
|
|
2020-08-03 18:34:15 +00:00
|
|
|
installSkel :: FilePath -> FilePath -> IO ()
|
2020-08-03 17:43:21 +00:00
|
|
|
#ifdef darwin_HOST_OS
|
2020-08-07 17:49:56 +00:00
|
|
|
installSkel _topdir basedir = do
|
2020-08-03 23:43:21 +00:00
|
|
|
whenM (doesDirectoryExist basedir) $
|
|
|
|
removeDirectoryRecursive basedir
|
2020-08-05 15:37:03 +00:00
|
|
|
createDirectoryIfMissing True (takeDirectory basedir)
|
2020-08-03 17:43:21 +00:00
|
|
|
unlessM (boolSystem "cp" [Param "-R", File "standalone/osx/git-annex.app", File basedir]) $
|
|
|
|
error "cp failed"
|
2020-08-03 18:34:15 +00:00
|
|
|
#else
|
|
|
|
installSkel topdir _basedir = do
|
2020-08-03 23:43:21 +00:00
|
|
|
whenM (doesDirectoryExist topdir) $
|
|
|
|
removeDirectoryRecursive topdir
|
2020-08-05 15:37:03 +00:00
|
|
|
createDirectoryIfMissing True (takeDirectory topdir)
|
2020-08-03 18:34:15 +00:00
|
|
|
unlessM (boolSystem "cp" [Param "-R", File "standalone/linux/skel", File topdir]) $
|
|
|
|
error "cp failed"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
installSkelRest :: FilePath -> FilePath -> Bool -> IO ()
|
|
|
|
#ifdef darwin_HOST_OS
|
2020-08-07 17:49:56 +00:00
|
|
|
installSkelRest _topdir basedir _hwcaplibs = do
|
2020-08-03 17:43:21 +00:00
|
|
|
plist <- lines <$> readFile "standalone/osx/Info.plist.template"
|
|
|
|
version <- getVersion
|
|
|
|
writeFile (basedir </> "Contents" </> "Info.plist")
|
|
|
|
(unlines (map (expandversion version) plist))
|
|
|
|
where
|
|
|
|
expandversion v l = replace "GIT_ANNEX_VERSION" v l
|
|
|
|
#else
|
2020-08-03 18:34:15 +00:00
|
|
|
installSkelRest topdir _basedir hwcaplibs = do
|
2020-08-03 17:43:21 +00:00
|
|
|
runshell <- lines <$> readFile "standalone/linux/skel/runshell"
|
|
|
|
-- GIT_ANNEX_PACKAGE_INSTALL can be set by a distributor and
|
|
|
|
-- runshell will be modified
|
|
|
|
gapi <- getEnv "GIT_ANNEX_PACKAGE_INSTALL"
|
|
|
|
writeFile (topdir </> "runshell")
|
|
|
|
(unlines (map (expandrunshell gapi) runshell))
|
2020-11-09 16:06:53 +00:00
|
|
|
modifyFileMode
|
|
|
|
(toRawFilePath (topdir </> "runshell"))
|
|
|
|
(addModes executeModes)
|
2020-08-03 17:43:21 +00:00
|
|
|
where
|
|
|
|
expandrunshell (Just gapi) l@"GIT_ANNEX_PACKAGE_INSTALL=" = l ++ gapi
|
2020-08-03 18:34:15 +00:00
|
|
|
-- This is an optimisation, that avoids the linker looking in
|
|
|
|
-- several directories for hwcap optimised libs, when there are
|
|
|
|
-- none.
|
|
|
|
expandrunshell _ l@"LD_HWCAP_MASK=" = l ++ if not hwcaplibs
|
|
|
|
then "0"
|
|
|
|
else ""
|
2020-08-03 17:43:21 +00:00
|
|
|
expandrunshell _ l = l
|
|
|
|
#endif
|
|
|
|
|
|
|
|
installGitAnnex :: FilePath -> IO ()
|
|
|
|
#ifdef darwin_HOST_OS
|
|
|
|
installGitAnnex topdir = go topdir
|
|
|
|
#else
|
|
|
|
installGitAnnex topdir = go (topdir </> "bin")
|
|
|
|
#endif
|
|
|
|
where
|
|
|
|
go bindir = do
|
|
|
|
createDirectoryIfMissing True bindir
|
|
|
|
unlessM (boolSystem "cp" [File "git-annex", File bindir]) $
|
2019-10-17 15:01:41 +00:00
|
|
|
error "cp failed"
|
2020-08-03 17:43:21 +00:00
|
|
|
unlessM (boolSystem "strip" [File (bindir </> "git-annex")]) $
|
|
|
|
error "strip failed"
|
2020-08-05 15:58:22 +00:00
|
|
|
createSymbolicLink "git-annex" (bindir </> "git-annex-shell")
|
|
|
|
createSymbolicLink "git-annex" (bindir </> "git-remote-tor-annex")
|
2024-05-06 16:58:38 +00:00
|
|
|
createSymbolicLink "git-annex" (bindir </> "git-remote-annex")
|
2019-10-17 15:01:41 +00:00
|
|
|
|
2013-12-30 17:19:22 +00:00
|
|
|
main :: IO ()
|
2012-12-14 19:52:44 +00:00
|
|
|
main = getArgs >>= go
|
|
|
|
where
|
2020-08-03 17:43:21 +00:00
|
|
|
go (topdir:basedir:[]) = do
|
2020-08-03 18:34:15 +00:00
|
|
|
installSkel topdir basedir
|
2020-08-03 17:43:21 +00:00
|
|
|
installGitAnnex topdir
|
|
|
|
installedbins <- installBundledPrograms topdir
|
2019-10-17 15:01:41 +00:00
|
|
|
installGitLibs topdir
|
2020-08-03 17:43:21 +00:00
|
|
|
installMagic topdir
|
|
|
|
installLocales topdir
|
2020-08-03 18:34:15 +00:00
|
|
|
hwcaplibs <- mklibs topdir installedbins
|
|
|
|
installSkelRest topdir basedir hwcaplibs
|
2020-08-03 17:43:21 +00:00
|
|
|
go _ = error "specify topdir and basedir"
|