54ad1b4cfb
Works around this bug in unix-compat: https://github.com/jacobstanley/unix-compat/issues/56 getFileStatus and other FilePath using functions in unix-compat do not do UNC conversion on Windows. Made Utility.RawFilePath use convertToWindowsNativeNamespace to do the necessary conversion on windows to support long filenames. Audited all imports of System.PosixCompat.Files to make sure that no functions that operate on FilePath were imported from it. Instead, use the equvilants from Utility.RawFilePath. In particular the re-export of that module in Common had to be removed, which led to lots of other changes throughout the code. The changes to Build.Configure, Build.DesktopFile, and Build.TestConfig make Utility.Directory not be needed to build setup. And so let it use Utility.RawFilePath, which depends on unix, which cannot be in setup-depends. Sponsored-by: Dartmouth College's Datalad project
175 lines
5.2 KiB
Haskell
175 lines
5.2 KiB
Haskell
{- Assistant installation
|
|
-
|
|
- Copyright 2012 Joey Hess <id@joeyh.name>
|
|
-
|
|
- Licensed under the GNU AGPL version 3 or higher.
|
|
-}
|
|
|
|
{-# LANGUAGE CPP #-}
|
|
|
|
module Assistant.Install where
|
|
|
|
import Assistant.Common
|
|
import Assistant.Install.AutoStart
|
|
import Config.Files
|
|
import Utility.FileMode
|
|
import Utility.Shell
|
|
import Utility.Tmp
|
|
import Utility.Env
|
|
import Utility.SshConfig
|
|
|
|
#ifdef darwin_HOST_OS
|
|
import Utility.OSX
|
|
#else
|
|
import Utility.FreeDesktop
|
|
import Assistant.Install.Menu
|
|
import Utility.UserInfo
|
|
import Utility.Android
|
|
#endif
|
|
|
|
import System.PosixCompat.Files (ownerExecuteMode)
|
|
|
|
standaloneAppBase :: IO (Maybe FilePath)
|
|
standaloneAppBase = getEnv "GIT_ANNEX_APP_BASE"
|
|
|
|
{- The standalone app does not have an installation process.
|
|
- So when it's run, it needs to set up autostarting of the assistant
|
|
- daemon, as well as writing the programFile, and putting the
|
|
- git-annex-shell and git-annex-wrapper wrapper scripts into ~/.ssh
|
|
-
|
|
- Note that this is done every time it's started, so if the user moves
|
|
- it around, the paths this sets up won't break.
|
|
-
|
|
- File manager hook script installation is done even for
|
|
- packaged apps, since it has to go into the user's home directory.
|
|
-}
|
|
ensureInstalled :: IO ()
|
|
ensureInstalled = ifM (isJust <$> getEnv "GIT_ANNEX_PACKAGE_INSTALL")
|
|
( go Nothing
|
|
, go =<< standaloneAppBase
|
|
)
|
|
where
|
|
go Nothing = installFileManagerHooks "git-annex"
|
|
go (Just base) = do
|
|
let program = base </> "git-annex"
|
|
programfile <- programFile
|
|
createDirectoryIfMissing True $
|
|
fromRawFilePath (parentDir (toRawFilePath programfile))
|
|
writeFile programfile program
|
|
|
|
#ifdef darwin_HOST_OS
|
|
autostartfile <- userAutoStart osxAutoStartLabel
|
|
installAutoStart program autostartfile
|
|
#else
|
|
ifM osAndroid
|
|
( do
|
|
-- Integration with the Termux:Boot app.
|
|
home <- myHomeDir
|
|
let bootfile = home </> ".termux" </> "boot" </> "git-annex"
|
|
unlessM (doesFileExist bootfile) $ do
|
|
createDirectoryIfMissing True (takeDirectory bootfile)
|
|
writeFile bootfile "git-annex assistant --autostart"
|
|
, do
|
|
menufile <- desktopMenuFilePath "git-annex" <$> userDataDir
|
|
icondir <- iconDir <$> userDataDir
|
|
installMenu program menufile base icondir
|
|
autostartfile <- autoStartPath "git-annex" <$> userConfigDir
|
|
installAutoStart program autostartfile
|
|
)
|
|
#endif
|
|
|
|
sshdir <- sshDir
|
|
let runshell var = "exec " ++ base </> "runshell " ++ var
|
|
let rungitannexshell var = runshell $ "git-annex-shell -c \"" ++ var ++ "\""
|
|
|
|
installWrapper (sshdir </> "git-annex-shell") $ unlines
|
|
[ shebang
|
|
, "set -e"
|
|
, "if [ \"x$SSH_ORIGINAL_COMMAND\" != \"x\" ]; then"
|
|
, rungitannexshell "$SSH_ORIGINAL_COMMAND"
|
|
, "else"
|
|
, rungitannexshell "$@"
|
|
, "fi"
|
|
]
|
|
installWrapper (sshdir </> "git-annex-wrapper") $ unlines
|
|
[ shebang
|
|
, "set -e"
|
|
, runshell "\"$@\""
|
|
]
|
|
|
|
installFileManagerHooks program
|
|
|
|
installWrapper :: FilePath -> String -> IO ()
|
|
installWrapper file content = do
|
|
curr <- catchDefaultIO "" $ readFileStrict file
|
|
when (curr /= content) $ do
|
|
createDirectoryIfMissing True (fromRawFilePath (parentDir (toRawFilePath file)))
|
|
viaTmp writeFile file content
|
|
modifyFileMode (toRawFilePath file) $
|
|
addModes [ownerExecuteMode]
|
|
|
|
installFileManagerHooks :: FilePath -> IO ()
|
|
#ifdef linux_HOST_OS
|
|
installFileManagerHooks program = unlessM osAndroid $ do
|
|
let actions = ["get", "drop", "undo"]
|
|
|
|
-- Gnome
|
|
nautilusScriptdir <- (\d -> d </> "nautilus" </> "scripts") <$> userDataDir
|
|
createDirectoryIfMissing True nautilusScriptdir
|
|
forM_ actions $
|
|
genNautilusScript nautilusScriptdir
|
|
|
|
-- KDE
|
|
userdata <- userDataDir
|
|
let kdeServiceMenusdir = userdata </> "kservices5" </> "ServiceMenus"
|
|
createDirectoryIfMissing True kdeServiceMenusdir
|
|
writeFile (kdeServiceMenusdir </> "git-annex.desktop")
|
|
(kdeDesktopFile actions)
|
|
where
|
|
genNautilusScript scriptdir action =
|
|
installscript (scriptdir </> scriptname action) $ unlines
|
|
[ shebang
|
|
, autoaddedcomment
|
|
, "exec " ++ program ++ " " ++ action ++ " --notify-start --notify-finish -- \"$@\""
|
|
]
|
|
scriptname action = "git-annex " ++ action
|
|
installscript f c = whenM (safetoinstallscript f) $ do
|
|
writeFile f c
|
|
modifyFileMode (toRawFilePath f) $ addModes [ownerExecuteMode]
|
|
safetoinstallscript f = catchDefaultIO True $
|
|
elem autoaddedcomment . lines <$> readFileStrict f
|
|
autoaddedcomment = "# " ++ autoaddedmsg ++ " (To disable, chmod 600 this file.)"
|
|
autoaddedmsg = "Automatically added by git-annex, do not edit."
|
|
|
|
kdeDesktopFile actions = unlines $ concat $
|
|
kdeDesktopHeader actions : map kdeDesktopAction actions
|
|
kdeDesktopHeader actions =
|
|
[ "# " ++ autoaddedmsg
|
|
, "[Desktop Entry]"
|
|
, "Type=Service"
|
|
, "ServiceTypes=all/allfiles"
|
|
, "MimeType=all/all;"
|
|
, "Actions=" ++ intercalate ";" (map kdeDesktopSection actions)
|
|
, "X-KDE-Priority=TopLevel"
|
|
, "X-KDE-Submenu=Git-Annex"
|
|
, "X-KDE-Icon=git-annex"
|
|
, "X-KDE-ServiceTypes=KonqPopupMenu/Plugin"
|
|
]
|
|
kdeDesktopSection command = "GitAnnex" ++ command
|
|
kdeDesktopAction command =
|
|
[ ""
|
|
, "[Desktop Action " ++ kdeDesktopSection command ++ "]"
|
|
, "Name=" ++ command
|
|
, "Icon=git-annex"
|
|
, unwords
|
|
[ "Exec=sh -c 'cd \"$(dirname \"$1\")\" &&"
|
|
, program
|
|
, command
|
|
, "--notify-start --notify-finish -- \"$1\"'"
|
|
, "false" -- this becomes $0 in sh, so unused
|
|
, "%f"
|
|
]
|
|
]
|
|
#else
|
|
installFileManagerHooks _ = noop
|
|
#endif
|