Skip to content

Commit 1bf43e2

Browse files
authored
Merge branch 'master' into f-f/add-refresh-flag
2 parents 4e28ff0 + e2ef8e9 commit 1bf43e2

File tree

11 files changed

+650
-40
lines changed

11 files changed

+650
-40
lines changed

src/Spago/Command/Fetch.purs

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,14 @@ run { packages: packagesRequestedToInstall, ensureRanges, isTest, isRepl } = do
224224
-- (we return them from inside there because we need to update the commit hashes)
225225
case workspace.packageSet.lockfile of
226226
Right _lockfile -> pure dependencies
227-
Left reason -> writeNewLockfile reason dependencies
227+
Left reason -> do
228+
-- When generating a lockfile, we need ALL git packages to be fetched so we can
229+
-- get their commit hashes. If a package is selected, depsToFetch only includes
230+
-- that package's deps, but the lockfile needs all packages.
231+
let allDeps = toAllDependencies allTransitiveDeps
232+
when (Map.keys allDeps /= Map.keys depsToFetch) do
233+
fetchPackagesToLocalCache allDeps
234+
writeNewLockfile reason dependencies
228235

229236
fetchPackagesToLocalCache :: a. Map PackageName Package -> Spago (FetchEnv a) Unit
230237
fetchPackagesToLocalCache packages = do
@@ -530,16 +537,24 @@ getPackageDependencies packageName package = case package of
530537
maybeManifest <- Registry.getManifestFromIndex packageName v
531538
pure $ maybeManifest <#> \(Manifest m) -> { core: m.dependencies, test: Map.empty }
532539
GitPackage p -> do
533-
-- Note: we get the package in local cache nonetheless,
534-
-- so we have guarantees about being able to fetch it
535-
{ rootPath } <- ask
536-
let packageLocation = Config.getLocalPackageLocation rootPath packageName package
537-
unlessM (FS.exists packageLocation) do
538-
getGitPackageInLocalCache packageName p
539540
case p.dependencies of
540-
Just (Dependencies dependencies) ->
541+
-- if dependencies are declared, we can use them directly without cloning.
542+
-- the package will be fetched later in fetchPackagesToLocalCache.
543+
Just (Dependencies dependencies) -> do
544+
-- when offline, verify the package is cached before proceeding
545+
{ offline, rootPath } <- ask
546+
let packageLocation = Config.getLocalPackageLocation rootPath packageName (GitPackage p)
547+
when (offline == Offline) do
548+
unlessM (FS.exists packageLocation) do
549+
die $ "Package '" <> PackageName.print packageName <> "' is not in the local cache, and Spago is running in offline mode - can't make progress."
541550
pure $ Just { core: map (fromMaybe Config.widestRange) dependencies, test: Map.empty }
551+
-- if the dependencies are not declared, then we need to clone the repo
552+
-- to look at the package manifest inside
542553
Nothing -> do
554+
{ rootPath } <- ask
555+
let packageLocation = Config.getLocalPackageLocation rootPath packageName package
556+
unlessM (FS.exists packageLocation) do
557+
getGitPackageInLocalCache packageName p
543558
readLocalDependencies $ Path.toGlobal $ maybe packageLocation (packageLocation </> _) p.subdir
544559
LocalPackage p -> do
545560
readLocalDependencies $ Path.global p.path

src/Spago/Config.purs

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -634,18 +634,41 @@ getLocalPackageLocation root name = case _ of
634634
-- inputs must map to two different outputs _and_ those outputs must differ by
635635
-- more than just casing.
636636
--
637-
-- The characters which are most commonly used in version and branch names are
638-
-- those which we allow through as they are (without escaping).
637+
-- The escape scheme uses:
638+
-- - `_` followed by lowercase for uppercase letters (A -> _a)
639+
-- - `_-` for underscore itself
640+
-- - `%` followed by mnemonic letter for special chars (/ -> %s, \ -> %b, : -> %c)
641+
-- - `%XX` hex fallback for other chars
639642
fileSystemCharEscape :: String -> String
640643
fileSystemCharEscape = String.toCodePointArray >>> map escapeCodePoint >>> Array.fold
641644
where
642-
commonlyUsedChars = map String.codePointFromChar [ '.', ',', '-', '_', '+' ]
643-
ignoreEscape = Unicode.isLower || Unicode.isDecDigit || flip Array.elem commonlyUsedChars
645+
-- Pass through: lowercase, digits, and safe punctuation (but NOT underscore)
646+
safeChars = map String.codePointFromChar [ '.', ',', '-', '+' ]
647+
isSafe = Unicode.isLower || Unicode.isDecDigit || flip Array.elem safeChars
644648

645649
escapeCodePoint :: CodePoint -> String
646650
escapeCodePoint cp
647-
| ignoreEscape cp = String.singleton cp
648-
| otherwise = append "%" $ Int.toStringAs Int.hexadecimal $ Enum.fromEnum cp
651+
| isSafe cp = String.singleton cp
652+
| cp == String.codePointFromChar '_' = "_-"
653+
| Unicode.isUpper cp = "_" <> String.singleton (Unicode.toLowerSimple cp)
654+
| otherwise = escapeSpecial cp
655+
656+
escapeSpecial :: CodePoint -> String
657+
escapeSpecial cp = case String.singleton cp of
658+
"/" -> "%s"
659+
"\\" -> "%b"
660+
":" -> "%c"
661+
"@" -> "%a"
662+
"~" -> "%t"
663+
"*" -> "%r"
664+
"?" -> "%q"
665+
"\"" -> "%d"
666+
"<" -> "%l"
667+
">" -> "%g"
668+
"|" -> "%p"
669+
" " -> "%w"
670+
"%" -> "%%"
671+
_ -> "%" <> Int.toStringAs Int.hexadecimal (Enum.fromEnum cp)
649672

650673
data WithTestGlobs
651674
= WithTestGlobs

src/Spago/Prelude.purs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ mkTemp' maybeSuffix = liftAff do
178178
sha <- Sha256.hashString $ show now <> fromMaybe "" maybeSuffix
179179
shaToHex sha
180180
-- Return the dir, but don't make it - that's the responsibility of the client
181-
let tempDirPath = Paths.paths.temp </> String.drop 50 random
181+
let tempDirPath = Paths.paths.temp </> String.drop 56 random
182182
pure tempDirPath
183183

184184
mkTemp :: forall m. MonadAff m => m Path.GlobalPath

test-fixtures/circular-dependencies.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ Reading Spago workspace configuration...
22

33
✓ Selecting package to build: bbb
44

5-
Cloning https://github.com/purescript/spago.git
65

76
✘ The following packages have circular dependencies:
87
- a

0 commit comments

Comments
 (0)