Global activate git path and ref (#3356)
diff --git a/lib/src/command/global_activate.dart b/lib/src/command/global_activate.dart
index a21386a..dc67f29 100644
--- a/lib/src/command/global_activate.dart
+++ b/lib/src/command/global_activate.dart
@@ -27,6 +27,11 @@
allowed: ['git', 'hosted', 'path'],
defaultsTo: 'hosted');
+ argParser.addOption('git-path', help: 'Path of git package in repository');
+
+ argParser.addOption('git-ref',
+ help: 'Git branch or commit to be retrieved');
+
argParser.addMultiOption('features',
abbr: 'f', help: 'Feature(s) to enable.', hide: true);
@@ -102,13 +107,24 @@
usageException('Unexpected $arguments ${toSentence(unexpected)}.');
}
+ if (argResults['source'] != 'git' &&
+ (argResults['git-path'] != null || argResults['git-ref'] != null)) {
+ usageException(
+ 'Options `--git-path` and `--git-ref` can only be used with --source=git.');
+ }
+
switch (argResults['source']) {
case 'git':
var repo = readArg('No Git repository given.');
- // TODO(rnystrom): Allow passing in a Git ref too.
validateNoExtraArgs();
- return globals.activateGit(repo, executables,
- features: features, overwriteBinStubs: overwrite);
+ return globals.activateGit(
+ repo,
+ executables,
+ features: features,
+ overwriteBinStubs: overwrite,
+ path: argResults['git-path'],
+ ref: argResults['git-ref'],
+ );
case 'hosted':
var package = readArg('No package to activate given.');
diff --git a/lib/src/global_packages.dart b/lib/src/global_packages.dart
index 773f2ec..b8ec3a9 100644
--- a/lib/src/global_packages.dart
+++ b/lib/src/global_packages.dart
@@ -85,23 +85,35 @@
/// If [overwriteBinStubs] is `true`, any binstubs that collide with
/// existing binstubs in other packages will be overwritten by this one's.
/// Otherwise, the previous ones will be preserved.
- Future<void> activateGit(String repo, List<String>? executables,
- {Map<String, FeatureDependency>? features,
- required bool overwriteBinStubs}) async {
+ Future<void> activateGit(
+ String repo,
+ List<String>? executables, {
+ Map<String, FeatureDependency>? features,
+ required bool overwriteBinStubs,
+ String? path,
+ String? ref,
+ }) async {
var name = await cache.git.getPackageNameFromRepo(repo);
// TODO(nweiz): Add some special handling for git repos that contain path
// dependencies. Their executables shouldn't be cached, and there should
// be a mechanism for redoing dependency resolution if a path pubspec has
// changed (see also issue 20499).
- PackageRef ref;
+ PackageRef packageRef;
try {
- ref = cache.git.source.parseRef(name, {'url': repo}, containingPath: '.');
+ packageRef = cache.git.source.parseRef(
+ name,
+ {
+ 'url': repo,
+ if (path != null) 'path': path,
+ if (ref != null) 'ref': ref,
+ },
+ containingPath: '.');
} on FormatException catch (e) {
throw ApplicationException(e.message);
}
await _installInCache(
- ref
+ packageRef
.withConstraint(VersionConstraint.any)
.withFeatures(features ?? const {}),
executables,
diff --git a/test/global/activate/git_package_test.dart b/test/global/activate/git_package_test.dart
index ee88de7..1fa6beb 100644
--- a/test/global/activate/git_package_test.dart
+++ b/test/global/activate/git_package_test.dart
@@ -2,6 +2,7 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
+import 'package:path/path.dart' as p;
import 'package:test/test.dart';
import '../../descriptor.dart' as d;
@@ -26,4 +27,66 @@
'Built foo:foo.\n'
'Activated foo 1.0.0 from Git repository "../foo.git".')));
});
+
+ test('activates a package from a Git repo with path and ref', () async {
+ ensureGit();
+
+ await d.git('foo.git', [
+ d.libPubspec('foo', '0.0.0'),
+ d.dir('bin', [d.file('foo.dart', "main() => print('0');")]),
+ d.dir(
+ 'sub',
+ [
+ d.libPubspec('foo', '1.0.0'),
+ d.dir('bin', [d.file('foo.dart', "main() => print('1');")])
+ ],
+ ),
+ ]).create();
+ await d.git('foo.git', [
+ d.dir(
+ 'sub',
+ [
+ d.libPubspec('foo', '2.0.0'),
+ d.dir('bin', [d.file('foo.dart', "main() => print('2');")])
+ ],
+ ),
+ ]).commit();
+ await d.git('foo.git', [
+ d.dir(
+ 'sub',
+ [
+ d.libPubspec('foo', '3.0.0'),
+ d.dir('bin', [d.file('foo.dart', "main() => print('3');")])
+ ],
+ ),
+ ]).commit();
+
+ await runPub(
+ args: [
+ 'global',
+ 'activate',
+ '-sgit',
+ '../foo.git',
+ '--git-ref=HEAD~',
+ '--git-path=sub/',
+ ],
+ output: allOf(
+ startsWith('Resolving dependencies...\n'
+ '+ foo 2.0.0 from git ../foo.git at'),
+ // Specific revision number goes here.
+ contains('in sub'),
+ endsWith('Building package executables...\n'
+ 'Built foo:foo.\n'
+ 'Activated foo 2.0.0 from Git repository "..${p.separator}foo.git".'),
+ ),
+ );
+ await runPub(
+ args: [
+ 'global',
+ 'run',
+ 'foo',
+ ],
+ output: contains('2'),
+ );
+ });
}
diff --git a/test/testdata/goldens/help_test/pub global activate --help.txt b/test/testdata/goldens/help_test/pub global activate --help.txt
index 5341266..29aab49 100644
--- a/test/testdata/goldens/help_test/pub global activate --help.txt
+++ b/test/testdata/goldens/help_test/pub global activate --help.txt
@@ -8,6 +8,8 @@
-h, --help Print this usage information.
-s, --source The source used to find the package.
[git, hosted (default), path]
+ --git-path Path of git package in repository
+ --git-ref Git branch or commit to be retrieved
--no-executables Do not put executables on PATH.
-x, --executable Executable(s) to place on PATH.
--overwrite Overwrite executables from other packages with the same