Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 2 additions & 6 deletions lib/src/pubspec.dart
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,7 @@ environment:

Pubspec(
String name, {
Version? version,
super.version,
Iterable<PackageRange>? dependencies,
Iterable<PackageRange>? devDependencies,
Iterable<PackageRange>? dependencyOverrides,
Expand Down Expand Up @@ -364,11 +364,7 @@ environment:
// This is a dummy value. Dependencies should already be resolved, so we
// never need to do relative resolutions.
_containingDescription = ResolvedRootDescription.fromDir('.'),
super(
fields == null ? YamlMap() : YamlMap.wrap(fields),
name: name,
version: version,
);
super(fields == null ? YamlMap() : YamlMap.wrap(fields), name: name);

/// Returns a Pubspec object for an already-parsed map representing its
/// contents.
Expand Down
2 changes: 1 addition & 1 deletion lib/src/solver/version_solver.dart
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ class VersionSolver {
);

try {
return await _systemCache.hosted.withPrefetching(() async {
return await _systemCache.hosted.withPrefetching(_systemCache, () async {
String? next = _root.name;
while (next != null) {
_propagate(next);
Expand Down
102 changes: 55 additions & 47 deletions lib/src/source/git.dart
Original file line number Diff line number Diff line change
Expand Up @@ -266,21 +266,6 @@ class GitSource extends CachedSource {
return p.url.normalize(parsed.toString());
}

/// Limit the number of concurrent git operations to 1.
// TODO(sigurdm): Use RateLimitedScheduler.
final Pool _pool = Pool(1);

/// A map from revision cache locations to futures that will complete once
/// they're finished being cloned.
///
/// This lets us avoid race conditions when getting multiple different
/// packages from the same repository.
final _revisionCacheClones = <String, Future<void>>{};

/// The paths to the canonical clones of repositories for which "git fetch"
/// has already been run during this run of pub.
final _updatedRepos = <String>{};

/// Given a Git repo that contains a pub package, gets the name of the pub
/// package.
///
Expand All @@ -305,7 +290,7 @@ class GitSource extends CachedSource {
containingDir: relativeTo,
tagPattern: tagPattern,
);
return await _pool.withResource(() async {
return await cache.gitCache.pool.withResource(() async {
await _ensureRepoCache(description, cache);
final path = _repoCachePath(description, cache);

Expand Down Expand Up @@ -370,7 +355,7 @@ class GitSource extends CachedSource {
if (description is! GitDescription) {
throw StateError('Called with wrong ref');
}
return await _pool.withResource(() async {
return await cache.gitCache.pool.withResource(() async {
await _ensureRepoCache(description, cache);
final path = _repoCachePath(description, cache);
final result = <PackageId>[];
Expand Down Expand Up @@ -417,7 +402,7 @@ class GitSource extends CachedSource {
if (description is! ResolvedGitDescription) {
throw StateError('Called with wrong ref');
}
final pubspec = await _pool.withResource(
final pubspec = await cache.gitCache.pool.withResource(
() => _describeUncached(id.toRef(), description.resolvedRef, cache),
);
if (pubspec.version != id.version) {
Expand All @@ -430,8 +415,6 @@ class GitSource extends CachedSource {
return pubspec;
}

final Map<(PackageRef, String), Pubspec> _pubspecAtRevisionCache = {};

/// Like [describeUncached], but takes a separate [ref] and Git [revision]
/// rather than a single ID.
Future<Pubspec> _describeUncached(
Expand All @@ -443,7 +426,10 @@ class GitSource extends CachedSource {
if (description is! GitDescription) {
throw ArgumentError('Wrong source');
}
return _pubspecAtRevisionCache[(ref, revision)] ??= await () async {
return cache.gitCache.pubspecAtRevisionCache[(
ref,
revision,
)] ??= await () async {
await _ensureRevision(description, revision, cache);
final resolvedDescription = ResolvedGitDescription(description, revision);
return Pubspec.parse(
Expand Down Expand Up @@ -473,7 +459,7 @@ class GitSource extends CachedSource {
PackageId id,
SystemCache cache,
) async {
return await _pool.withResource(() async {
return await cache.gitCache.pool.withResource(() async {
var didUpdate = false;
final ref = id.toRef();
final description = ref.description;
Expand All @@ -495,25 +481,28 @@ class GitSource extends CachedSource {

final revisionCachePath = _revisionCachePath(id, cache);
final path = description.path;
await _revisionCacheClones.putIfAbsent(revisionCachePath, () async {
if (!entryExists(revisionCachePath)) {
await _cloneViaTemp(
_repoCachePath(description, cache),
revisionCachePath,
cache,
);
await git.run([
'config',
'remote.origin.lfsurl',
description.url,
], workingDir: revisionCachePath);
await _checkOut(revisionCachePath, resolvedRef);
_writePackageList(revisionCachePath, [path]);
didUpdate = true;
} else {
didUpdate |= _updatePackageList(revisionCachePath, path);
}
});
await cache.gitCache.revisionCacheClones.putIfAbsent(
revisionCachePath,
() async {
if (!entryExists(revisionCachePath)) {
await _cloneViaTemp(
_repoCachePath(description, cache),
revisionCachePath,
cache,
);
await git.run([
'config',
'remote.origin.lfsurl',
description.url,
], workingDir: revisionCachePath);
await _checkOut(revisionCachePath, resolvedRef);
_writePackageList(revisionCachePath, [path]);
didUpdate = true;
} else {
didUpdate |= _updatePackageList(revisionCachePath, path);
}
},
);
return DownloadPackageResult(id, didUpdate: didUpdate);
});
}
Expand Down Expand Up @@ -646,7 +635,7 @@ class GitSource extends CachedSource {
SystemCache cache,
) async {
final path = _repoCachePath(description, cache);
if (_updatedRepos.contains(path)) return false;
if (cache.gitCache.updatedRepos.contains(path)) return false;

await _deleteGitRepoIfInvalid(path);

Expand All @@ -672,7 +661,7 @@ class GitSource extends CachedSource {
SystemCache cache,
) async {
final path = _repoCachePath(description, cache);
if (_updatedRepos.contains(path)) return false;
if (cache.gitCache.updatedRepos.contains(path)) return false;

await _deleteGitRepoIfInvalid(path);

Expand All @@ -693,14 +682,14 @@ class GitSource extends CachedSource {
SystemCache cache,
) async {
final path = _repoCachePath(description, cache);
assert(!_updatedRepos.contains(path));
assert(!cache.gitCache.updatedRepos.contains(path));
try {
await _cloneViaTemp(description.url, path, cache, mirror: true);
} catch (_) {
await _deleteGitRepoIfInvalid(path);
rethrow;
}
_updatedRepos.add(path);
cache.gitCache.updatedRepos.add(path);
}

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

Expand Down Expand Up @@ -1226,3 +1215,22 @@ RegExp compileTagPattern(String tagPattern) {
r'$',
);
}

/// State that is cached for the GitSource.
final class GitSourceCache {
/// Limit the number of concurrent git operations to 1.
final pool = Pool(1);

/// A map from revision cache locations to futures that will complete once
/// they're finished being cloned.
///
/// This lets us avoid race conditions when getting multiple different
/// packages from the same repository.
final revisionCacheClones = <String, Future<void>>{};

/// The paths to the canonical clones of repositories for which "git fetch"
/// has already been run during this run of pub.
final updatedRepos = <String>{};

final pubspecAtRevisionCache = <(PackageRef, String), Pubspec>{};
}
Loading
Loading