| ... |
... |
@@ -53,9 +53,17 @@ import System.FilePath as FilePath |
|
53
|
53
|
-- ExternalUnitDatabases
|
|
54
|
54
|
-- ----------------------------------------------------------------------------
|
|
55
|
55
|
|
|
|
56
|
+-- | A normalised 'OsPath' that we use as the key to cache 'UnitDatabase's.
|
|
|
57
|
+--
|
|
|
58
|
+-- Removes trailing path separators and unit database paths starting with @./@.
|
|
|
59
|
+newtype NormalisedUnitDbLoc = NormalisedUnitDbLoc OsPath
|
|
|
60
|
+ deriving (Eq, Ord)
|
|
|
61
|
+
|
|
56
|
62
|
-- | Caches unit databases in-memory.
|
|
57
|
63
|
data ExternalUnitDatabases unit = ExternalUnitDatabases
|
|
58
|
|
- { eud_cachedDatabases :: !(Map OsPath (UnitDatabase unit))
|
|
|
64
|
+ { eud_cachedDatabases :: !(Map NormalisedUnitDbLoc (UnitDatabase unit))
|
|
|
65
|
+ -- ^ The 'Map' is keyed by a normalised 'OsPath', ensuring that 'lookupExternalUnitDatabases'
|
|
|
66
|
+ -- will never get confused by a stray @./@ or trailing @/@.
|
|
59
|
67
|
}
|
|
60
|
68
|
|
|
61
|
69
|
emptyExternalUnitDatabases :: ExternalUnitDatabases unit
|
| ... |
... |
@@ -67,18 +75,20 @@ emptyExternalUnitDatabases = |
|
67
|
75
|
insertExternalUnitDatabases :: UnitDatabase unit -> ExternalUnitDatabases unit -> ExternalUnitDatabases unit
|
|
68
|
76
|
insertExternalUnitDatabases unit_db eud =
|
|
69
|
77
|
ExternalUnitDatabases
|
|
70
|
|
- { eud_cachedDatabases = Map.insert (unitDatabasePath unit_db) unit_db (eud_cachedDatabases eud)
|
|
|
78
|
+ { eud_cachedDatabases =
|
|
|
79
|
+ Map.insert (normalisedUnitDatabaseKey unit_db) unit_db (eud_cachedDatabases eud)
|
|
71
|
80
|
}
|
|
72
|
81
|
|
|
73
|
82
|
deleteExternalUnitDatabases :: OsPath -> ExternalUnitDatabases unit -> ExternalUnitDatabases unit
|
|
74
|
83
|
deleteExternalUnitDatabases unit_db_path eud =
|
|
75
|
84
|
ExternalUnitDatabases
|
|
76
|
|
- { eud_cachedDatabases = Map.delete unit_db_path (eud_cachedDatabases eud)
|
|
|
85
|
+ { eud_cachedDatabases =
|
|
|
86
|
+ Map.delete (normalisedUnitDatabaseKeyOsPath unit_db_path) (eud_cachedDatabases eud)
|
|
77
|
87
|
}
|
|
78
|
88
|
|
|
79
|
89
|
lookupExternalUnitDatabases :: OsPath -> ExternalUnitDatabases unit -> Maybe (UnitDatabase unit)
|
|
80
|
90
|
lookupExternalUnitDatabases key eud =
|
|
81
|
|
- Map.lookup key (eud_cachedDatabases eud)
|
|
|
91
|
+ Map.lookup (normalisedUnitDatabaseKeyOsPath key) (eud_cachedDatabases eud)
|
|
82
|
92
|
|
|
83
|
93
|
-- ----------------------------------------------------------------------------
|
|
84
|
94
|
-- UnitDatabase
|
| ... |
... |
@@ -87,12 +97,38 @@ lookupExternalUnitDatabases key eud = |
|
87
|
97
|
-- | Unit database entry.
|
|
88
|
98
|
data UnitDatabase unit = UnitDatabase
|
|
89
|
99
|
{ unitDatabasePath :: OsPath
|
|
|
100
|
+ -- ^ On-disk location of the unit database.
|
|
|
101
|
+ --
|
|
90
|
102
|
, unitDatabaseUnits :: [GenUnitInfo unit]
|
|
|
103
|
+ -- ^ Units read from the database located at 'unitDatabasePath'.
|
|
|
104
|
+ --
|
|
|
105
|
+ -- These units have the @$pkgroot@ variable already resolved.
|
|
91
|
106
|
}
|
|
92
|
107
|
|
|
93
|
108
|
instance (Outputable u) => Outputable (UnitDatabase u) where
|
|
94
|
109
|
ppr (UnitDatabase fp _u) = text "DB:" <+> ppr fp
|
|
95
|
110
|
|
|
|
111
|
+normalisedUnitDatabaseKey :: UnitDatabase unit -> NormalisedUnitDbLoc
|
|
|
112
|
+normalisedUnitDatabaseKey unit_db = normalisedUnitDatabaseKeyOsPath $ unitDatabasePath unit_db
|
|
|
113
|
+
|
|
|
114
|
+-- | Normalise the unit database location and drop trailing path separators.
|
|
|
115
|
+--
|
|
|
116
|
+-- This ensures that two databases that point to the same location can be cached.
|
|
|
117
|
+--
|
|
|
118
|
+-- We need to remove trailing slash from the 'OsPath' before calculating @$pkgroot@ (Fix #16360)
|
|
|
119
|
+normalisedUnitDatabaseKeyOsPath :: OsPath -> NormalisedUnitDbLoc
|
|
|
120
|
+normalisedUnitDatabaseKeyOsPath db_path =
|
|
|
121
|
+ NormalisedUnitDbLoc $ OsPath.dropTrailingPathSeparator $ OsPath.normalise db_path
|
|
|
122
|
+
|
|
|
123
|
+-- | Get the root location of a unit database.
|
|
|
124
|
+-- Used to replace @$pkgroot@ variables in the 'GenericUnitInfo'.
|
|
|
125
|
+unitDatabaseRoot :: OsPath -> OsPath
|
|
|
126
|
+unitDatabaseRoot p =
|
|
|
127
|
+ let
|
|
|
128
|
+ NormalisedUnitDbLoc np = normalisedUnitDatabaseKeyOsPath p
|
|
|
129
|
+ in
|
|
|
130
|
+ OsPath.takeDirectory np
|
|
|
131
|
+
|
|
96
|
132
|
-- ----------------------------------------------------------------------------
|
|
97
|
133
|
--
|
|
98
|
134
|
-- Merging databases
|
| ... |
... |
@@ -258,14 +294,12 @@ readUnitDatabase logger cfg conf_file = do |
|
258
|
294
|
"can't find a package database at " ++ show conf_file
|
|
259
|
295
|
|
|
260
|
296
|
let
|
|
261
|
|
- -- Fix #16360: remove trailing slash from conf_file before calculating pkgroot
|
|
262
|
|
- conf_file' = OsPath.dropTrailingPathSeparator conf_file
|
|
263
|
297
|
top_dir = OsPath.unsafeEncodeUtf (unitDbConfigGHCDir cfg)
|
|
264
|
|
- pkgroot = OsPath.takeDirectory conf_file'
|
|
|
298
|
+ pkgroot = unitDatabaseRoot conf_file
|
|
265
|
299
|
pkg_configs1 = map (mungeUnitInfo top_dir pkgroot . mapUnitInfo (\(UnitKey x) -> UnitId x) . mkUnitKeyInfo)
|
|
266
|
300
|
proto_pkg_configs
|
|
267
|
301
|
--
|
|
268
|
|
- return $ UnitDatabase conf_file' pkg_configs1
|
|
|
302
|
+ return $ UnitDatabase conf_file pkg_configs1
|
|
269
|
303
|
where
|
|
270
|
304
|
readDirStyleUnitInfo :: OsPath -> IO [DbUnitInfo]
|
|
271
|
305
|
readDirStyleUnitInfo conf_dir = do
|