File: V9.hs

package info (click to toggle)
git-annex 10.20230126-3
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 69,344 kB
  • sloc: haskell: 74,654; javascript: 9,103; sh: 1,304; makefile: 203; perl: 136; ansic: 44
file content (105 lines) | stat: -rw-r--r-- 3,291 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
{- git-annex v9 -> v10 upgrade support
 -
 - Copyright 2022 Joey Hess <id@joeyh.name>
 -
 - Licensed under the GNU AGPL version 3 or higher.
 -}

module Upgrade.V9 where

import Annex.Common
import qualified Annex
import Types.Upgrade
import Annex.Content
import Annex.Perms
import Annex.LockFile
import Annex.Version
import Git.ConfigTypes
import Types.RepoVersion
import Logs.Upgrade
import Utility.Daemon

import Data.Time.Clock.POSIX

upgrade :: Bool -> Annex UpgradeResult
upgrade automatic
	| automatic = ifM oldprocessesdanger
		( return UpgradeDeferred
		, performUpgrade automatic
		)
	| otherwise = ifM (oldprocessesdanger <&&> (not <$> Annex.getRead Annex.force))
		( do
			warning $ unlines unsafeupgrade
			return UpgradeDeferred
		, performUpgrade automatic
		)
  where
	{- Wait until a year after the v9 upgrade, to give time for
	 - any old processes that were running before the v9 upgrade
	 - to finish. Such old processes lock content using the old method,
	 - and it is not safe for such to still be running after
	 - this upgrade. -}
	oldprocessesdanger = timeOfUpgrade (RepoVersion 9) >>= \case
		Just t -> do
			now <- liftIO getPOSIXTime
			if now < t + 365*24*60*60
				then return True
				else assistantrunning
		-- Initialized at v9, so no old process danger exists.
		Nothing -> pure False

	{- Skip upgrade when git-annex assistant (or watch) is running,
	 - because these are long-running daemons that could conceivably
	 - run for an entire year and so predate the v9 upgrade. -}
	assistantrunning = do
		pidfile <- fromRepo gitAnnexPidFile
		isJust <$> liftIO (checkDaemon (fromRawFilePath pidfile))
	
	unsafeupgrade =
		[ "Not upgrading from v9 to v10, because there may be git-annex"
		, "processes running that predate the v9 upgrade. Upgrading with"
		, "such processes running could lead to data loss. This upgrade"
		, "will be deferred until one year after the v9 upgrade to make"
		, "sure there are no such old processes running."
		, "(Use --force to upgrade immediately.)"
		]

performUpgrade :: Bool -> Annex UpgradeResult
performUpgrade automatic = do
	unless automatic $
		showAction "v9 to v10"
	
	{- Take a lock to ensure that there are no other git-annex
	 - processes running that are using the old content locking method. -}
	lck <- fromRepo gitAnnexContentLockLock
	withExclusiveLock lck $ do
		{- When core.sharedRepository is set, object files
		 - used to have their write bits set. That can now be
		 - removed, if the user the upgrade is running as has
		 - permission to remove it.
		 - (Otherwise, a later fsck will fix up the permissions.) -}
		withShared $ \sr -> case sr of
			GroupShared -> removewrite sr
			AllShared -> removewrite sr
			_ -> return ()

		{- Set the new version while still holding the lock,
		 - so that any other process waiting for the lock will
		 - be able to detect that the upgrade happened. -}
		setVersion newver

		return UpgradeSuccess
  where
	newver = RepoVersion 10

	removewrite sr = do
		ks <- listKeys InAnnex
		forM_ ks $ \k -> do
			obj <- calcRepo (gitAnnexLocation k)
			keystatus <- getKeyStatus k
			case keystatus of
				KeyPresent -> void $ tryIO $
					freezeContent'' sr obj (Just newver)
				KeyUnlockedThin -> return ()
				KeyLockedThin -> return ()
				KeyMissing -> return ()