Skip to content

Commit b5263b3

Browse files
authored
Separate state for sources (#4811)
1 parent 764c4b3 commit b5263b3

6 files changed

Lines changed: 138 additions & 88 deletions

File tree

lib/src/pubspec.dart

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -331,7 +331,7 @@ environment:
331331

332332
Pubspec(
333333
String name, {
334-
Version? version,
334+
super.version,
335335
Iterable<PackageRange>? dependencies,
336336
Iterable<PackageRange>? devDependencies,
337337
Iterable<PackageRange>? dependencyOverrides,
@@ -364,11 +364,7 @@ environment:
364364
// This is a dummy value. Dependencies should already be resolved, so we
365365
// never need to do relative resolutions.
366366
_containingDescription = ResolvedRootDescription.fromDir('.'),
367-
super(
368-
fields == null ? YamlMap() : YamlMap.wrap(fields),
369-
name: name,
370-
version: version,
371-
);
367+
super(fields == null ? YamlMap() : YamlMap.wrap(fields), name: name);
372368

373369
/// Returns a Pubspec object for an already-parsed map representing its
374370
/// contents.

lib/src/solver/version_solver.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ class VersionSolver {
126126
);
127127

128128
try {
129-
return await _systemCache.hosted.withPrefetching(() async {
129+
return await _systemCache.hosted.withPrefetching(_systemCache, () async {
130130
String? next = _root.name;
131131
while (next != null) {
132132
_propagate(next);

lib/src/source/git.dart

Lines changed: 55 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -266,21 +266,6 @@ class GitSource extends CachedSource {
266266
return p.url.normalize(parsed.toString());
267267
}
268268

269-
/// Limit the number of concurrent git operations to 1.
270-
// TODO(sigurdm): Use RateLimitedScheduler.
271-
final Pool _pool = Pool(1);
272-
273-
/// A map from revision cache locations to futures that will complete once
274-
/// they're finished being cloned.
275-
///
276-
/// This lets us avoid race conditions when getting multiple different
277-
/// packages from the same repository.
278-
final _revisionCacheClones = <String, Future<void>>{};
279-
280-
/// The paths to the canonical clones of repositories for which "git fetch"
281-
/// has already been run during this run of pub.
282-
final _updatedRepos = <String>{};
283-
284269
/// Given a Git repo that contains a pub package, gets the name of the pub
285270
/// package.
286271
///
@@ -305,7 +290,7 @@ class GitSource extends CachedSource {
305290
containingDir: relativeTo,
306291
tagPattern: tagPattern,
307292
);
308-
return await _pool.withResource(() async {
293+
return await cache.gitCache.pool.withResource(() async {
309294
await _ensureRepoCache(description, cache);
310295
final path = _repoCachePath(description, cache);
311296

@@ -370,7 +355,7 @@ class GitSource extends CachedSource {
370355
if (description is! GitDescription) {
371356
throw StateError('Called with wrong ref');
372357
}
373-
return await _pool.withResource(() async {
358+
return await cache.gitCache.pool.withResource(() async {
374359
await _ensureRepoCache(description, cache);
375360
final path = _repoCachePath(description, cache);
376361
final result = <PackageId>[];
@@ -417,7 +402,7 @@ class GitSource extends CachedSource {
417402
if (description is! ResolvedGitDescription) {
418403
throw StateError('Called with wrong ref');
419404
}
420-
final pubspec = await _pool.withResource(
405+
final pubspec = await cache.gitCache.pool.withResource(
421406
() => _describeUncached(id.toRef(), description.resolvedRef, cache),
422407
);
423408
if (pubspec.version != id.version) {
@@ -430,8 +415,6 @@ class GitSource extends CachedSource {
430415
return pubspec;
431416
}
432417

433-
final Map<(PackageRef, String), Pubspec> _pubspecAtRevisionCache = {};
434-
435418
/// Like [describeUncached], but takes a separate [ref] and Git [revision]
436419
/// rather than a single ID.
437420
Future<Pubspec> _describeUncached(
@@ -443,7 +426,10 @@ class GitSource extends CachedSource {
443426
if (description is! GitDescription) {
444427
throw ArgumentError('Wrong source');
445428
}
446-
return _pubspecAtRevisionCache[(ref, revision)] ??= await () async {
429+
return cache.gitCache.pubspecAtRevisionCache[(
430+
ref,
431+
revision,
432+
)] ??= await () async {
447433
await _ensureRevision(description, revision, cache);
448434
final resolvedDescription = ResolvedGitDescription(description, revision);
449435
return Pubspec.parse(
@@ -473,7 +459,7 @@ class GitSource extends CachedSource {
473459
PackageId id,
474460
SystemCache cache,
475461
) async {
476-
return await _pool.withResource(() async {
462+
return await cache.gitCache.pool.withResource(() async {
477463
var didUpdate = false;
478464
final ref = id.toRef();
479465
final description = ref.description;
@@ -495,25 +481,28 @@ class GitSource extends CachedSource {
495481

496482
final revisionCachePath = _revisionCachePath(id, cache);
497483
final path = description.path;
498-
await _revisionCacheClones.putIfAbsent(revisionCachePath, () async {
499-
if (!entryExists(revisionCachePath)) {
500-
await _cloneViaTemp(
501-
_repoCachePath(description, cache),
502-
revisionCachePath,
503-
cache,
504-
);
505-
await git.run([
506-
'config',
507-
'remote.origin.lfsurl',
508-
description.url,
509-
], workingDir: revisionCachePath);
510-
await _checkOut(revisionCachePath, resolvedRef);
511-
_writePackageList(revisionCachePath, [path]);
512-
didUpdate = true;
513-
} else {
514-
didUpdate |= _updatePackageList(revisionCachePath, path);
515-
}
516-
});
484+
await cache.gitCache.revisionCacheClones.putIfAbsent(
485+
revisionCachePath,
486+
() async {
487+
if (!entryExists(revisionCachePath)) {
488+
await _cloneViaTemp(
489+
_repoCachePath(description, cache),
490+
revisionCachePath,
491+
cache,
492+
);
493+
await git.run([
494+
'config',
495+
'remote.origin.lfsurl',
496+
description.url,
497+
], workingDir: revisionCachePath);
498+
await _checkOut(revisionCachePath, resolvedRef);
499+
_writePackageList(revisionCachePath, [path]);
500+
didUpdate = true;
501+
} else {
502+
didUpdate |= _updatePackageList(revisionCachePath, path);
503+
}
504+
},
505+
);
517506
return DownloadPackageResult(id, didUpdate: didUpdate);
518507
});
519508
}
@@ -646,7 +635,7 @@ class GitSource extends CachedSource {
646635
SystemCache cache,
647636
) async {
648637
final path = _repoCachePath(description, cache);
649-
if (_updatedRepos.contains(path)) return false;
638+
if (cache.gitCache.updatedRepos.contains(path)) return false;
650639

651640
await _deleteGitRepoIfInvalid(path);
652641

@@ -672,7 +661,7 @@ class GitSource extends CachedSource {
672661
SystemCache cache,
673662
) async {
674663
final path = _repoCachePath(description, cache);
675-
if (_updatedRepos.contains(path)) return false;
664+
if (cache.gitCache.updatedRepos.contains(path)) return false;
676665

677666
await _deleteGitRepoIfInvalid(path);
678667

@@ -693,14 +682,14 @@ class GitSource extends CachedSource {
693682
SystemCache cache,
694683
) async {
695684
final path = _repoCachePath(description, cache);
696-
assert(!_updatedRepos.contains(path));
685+
assert(!cache.gitCache.updatedRepos.contains(path));
697686
try {
698687
await _cloneViaTemp(description.url, path, cache, mirror: true);
699688
} catch (_) {
700689
await _deleteGitRepoIfInvalid(path);
701690
rethrow;
702691
}
703-
_updatedRepos.add(path);
692+
cache.gitCache.updatedRepos.add(path);
704693
}
705694

706695
/// Runs "git fetch" in the canonical clone of the repository referred to by
@@ -714,9 +703,9 @@ class GitSource extends CachedSource {
714703
SystemCache cache,
715704
) async {
716705
final path = _repoCachePath(description, cache);
717-
if (_updatedRepos.contains(path)) return false;
706+
if (cache.gitCache.updatedRepos.contains(path)) return false;
718707
await git.run([_gitDirArg(path), 'fetch'], workingDir: path);
719-
_updatedRepos.add(path);
708+
cache.gitCache.updatedRepos.add(path);
720709
return true;
721710
}
722711

@@ -1226,3 +1215,22 @@ RegExp compileTagPattern(String tagPattern) {
12261215
r'$',
12271216
);
12281217
}
1218+
1219+
/// State that is cached for the GitSource.
1220+
final class GitSourceCache {
1221+
/// Limit the number of concurrent git operations to 1.
1222+
final pool = Pool(1);
1223+
1224+
/// A map from revision cache locations to futures that will complete once
1225+
/// they're finished being cloned.
1226+
///
1227+
/// This lets us avoid race conditions when getting multiple different
1228+
/// packages from the same repository.
1229+
final revisionCacheClones = <String, Future<void>>{};
1230+
1231+
/// The paths to the canonical clones of repositories for which "git fetch"
1232+
/// has already been run during this run of pub.
1233+
final updatedRepos = <String>{};
1234+
1235+
final pubspecAtRevisionCache = <(PackageRef, String), Pubspec>{};
1236+
}

0 commit comments

Comments
 (0)