File: Import.hs

package info (click to toggle)
git-annex 10.20251029-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 75,300 kB
  • sloc: haskell: 91,492; javascript: 9,103; sh: 1,593; makefile: 216; perl: 137; ansic: 44
file content (73 lines) | stat: -rw-r--r-- 2,594 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
{- git-annex import logs
 -
 - Copyright 2023-2025 Joey Hess <id@joeyh.name>
 -
 - Licensed under the GNU AGPL version 3 or higher.
 -}

module Logs.Import (
	recordContentIdentifierTree,
	getContentIdentifierTree
) where

import Annex.Common
import Git.Types
import Git.Sha
import Logs.File
import Logs.Export

import qualified Data.ByteString.Lazy as L
import qualified Data.ByteString.Char8 as S8
import qualified Data.Set as S

{- Records the sha of a tree that contains hashes of ContentIdentifiers
 - that were imported from a remote.
 -
 - The sha is on the first line of the log file, and following it
 - is a line with the the currently exported treeishs, and then a line with
 - the incomplete exported treeishes.
 -}
recordContentIdentifierTree :: UUID -> Sha -> Annex ()
recordContentIdentifierTree u t = do
	l <- calcRepo' (gitAnnexImportLog u)
	exported <- getExport u
	writeLogFile l $ unlines
		[ fromRef t
		, unwords $ map fromRef $ exportedTreeishes exported
		, unwords $ map fromRef $ incompleteExportedTreeishes exported
		]

{- Gets the ContentIdentifier tree last recorded for a remote.
 -
 - This returns Nothing if no tree was recorded yet. 
 -
 - It also returns Nothing when there have been changes to what is exported
 - to the remote since the tree was recorded. That avoids a problem where
 - diffing from the current Contentidentifier tree to the previous tree
 - would miss changes that were made to a remote by an export, but were
 - later undone manually. For example, if a file was exported to the remote,
 - and then the file was manually removed from the remote, the current tree
 - would not contain the file, and neither would the previous tree.
 - So diffing between the trees would miss that removal. The removed
 - file would then remain in the imported tree.
 -}
getContentIdentifierTree :: UUID -> Annex (Maybe Sha)
getContentIdentifierTree u = do
	l <- calcRepo' (gitAnnexImportLog u)
	-- This is safe because the log file is written atomically.
	ls <- calcLogFileUnsafe l [] (\v ls -> L.toStrict v : ls)
	exported <- getExport u
	return $ case reverse ls of
		-- Subsequent lines are ignored. This leaves room for future
		-- expansion of what is logged.
		(a:b:c:_) -> do
			t <- extractSha a
			exportedtreeishs <- mapM extractSha (S8.words b)
			incompleteexportedtreeishs <- mapM extractSha (S8.words c)
			if same exportedtreeishs (exportedTreeishes exported) && 
			   same incompleteexportedtreeishs (incompleteExportedTreeishes exported)
				then Just t
				else Nothing
		_ -> Nothing
  where
	same l1 l2 = S.fromList l1 == S.fromList l2