Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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.
class GitSourceCache {
Comment thread
sigurdm marked this conversation as resolved.
Outdated
/// 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