Fix pub upgrade to work with new arguments (#74060)

diff --git a/packages/flutter_tools/lib/src/commands/packages.dart b/packages/flutter_tools/lib/src/commands/packages.dart
index fcbdb52..615733d 100644
--- a/packages/flutter_tools/lib/src/commands/packages.dart
+++ b/packages/flutter_tools/lib/src/commands/packages.dart
@@ -20,7 +20,10 @@
 class PackagesCommand extends FlutterCommand {
   PackagesCommand() {
     addSubcommand(PackagesGetCommand('get', false));
-    addSubcommand(PackagesGetCommand('upgrade', true));
+    //addSubcommand(PackagesGetCommand('upgrade', true));
+    addSubcommand(PackagesInteractiveGetCommand('upgrade', 'Upgrade the current package\'s dependencies to latest versions.'));
+    addSubcommand(PackagesInteractiveGetCommand('add', 'Add a dependency to pubspec.yaml.'));
+    addSubcommand(PackagesInteractiveGetCommand('remove', 'Removes a dependency from the current package.'));
     addSubcommand(PackagesTestCommand());
     addSubcommand(PackagesForwardCommand('publish', 'Publish the current package to pub.dartlang.org', requiresPubspec: true));
     addSubcommand(PackagesForwardCommand('downgrade', 'Downgrade packages in a Flutter project', requiresPubspec: true));
@@ -29,6 +32,8 @@
     addSubcommand(PackagesForwardCommand('cache', 'Work with the Pub system cache'));
     addSubcommand(PackagesForwardCommand('version', 'Print Pub version'));
     addSubcommand(PackagesForwardCommand('uploader', 'Manage uploaders for a package on pub.dev'));
+    addSubcommand(PackagesForwardCommand('login', 'Log into pub.dev.'));
+    addSubcommand(PackagesForwardCommand('logout', 'Log out of pub.dev.'));
     addSubcommand(PackagesForwardCommand('global', 'Work with Pub global packages'));
     addSubcommand(PackagesForwardCommand('outdated', 'Analyze dependencies to find which ones can be upgraded', requiresPubspec: true));
     addSubcommand(PackagesPassthroughCommand());
@@ -253,3 +258,82 @@
     return FlutterCommandResult.success();
   }
 }
+
+class PackagesInteractiveGetCommand extends FlutterCommand {
+  PackagesInteractiveGetCommand(this._commandName, this._description) {
+    requiresPubspecYaml();
+  }
+
+  @override
+  ArgParser argParser = ArgParser.allowAnything();
+
+  final String _commandName;
+  final String _description;
+
+  @override
+  String get name => _commandName;
+
+  @override
+  String get description {
+    return '$_description.\n'
+           'This runs the "pub" tool in a Flutter context.';
+  }
+
+  @override
+  String get invocation {
+    return '${runner.executableName} pub $_commandName [<arguments...>]';
+  }
+
+  @override
+  Future<FlutterCommandResult> runCommand() async {
+    List<String> rest = argResults.rest;
+    String target;
+    if (rest.length == 1 &&
+        (rest[0].contains('/') ||
+            rest[0].contains(r'\'))) {
+      // HACK: Supporting flutter specific behavior where you can pass a
+      //       folder to the command.
+      target = findProjectRoot(rest[0]);
+      rest = <String>[];
+    } else {
+      target = findProjectRoot();
+    }
+    if (target == null) {
+      throwToolExit('Expected to find project root in '
+          'current working directory.');
+    }
+    final FlutterProject flutterProject = FlutterProject.fromPath(target);
+
+    if (flutterProject.manifest.generateSyntheticPackage) {
+      final Environment environment = Environment(
+        artifacts: globals.artifacts,
+        logger: globals.logger,
+        cacheDir: globals.cache.getRoot(),
+        engineVersion: globals.flutterVersion.engineRevision,
+        fileSystem: globals.fs,
+        flutterRootDir: globals.fs.directory(Cache.flutterRoot),
+        outputDir: globals.fs.directory(getBuildDirectory()),
+        processManager: globals.processManager,
+        projectDir: flutterProject.directory,
+      );
+
+      await generateLocalizationsSyntheticPackage(
+        environment: environment,
+        buildSystem: globals.buildSystem,
+      );
+    }
+
+    final List<String> subArgs = rest.toList()
+      ..removeWhere((String arg) => arg == '--');
+    await pub.interactively(
+      <String>[name, ...subArgs],
+      directory: target,
+      stdio: globals.stdio,
+      touchesPackageConfig: true,
+      generateSyntheticPackage: flutterProject.manifest.generateSyntheticPackage,
+    );
+
+    await flutterProject.regeneratePlatformSpecificTooling();
+    return FlutterCommandResult.success();
+  }
+}
diff --git a/packages/flutter_tools/lib/src/dart/pub.dart b/packages/flutter_tools/lib/src/dart/pub.dart
index ed6ace0..defb78c 100644
--- a/packages/flutter_tools/lib/src/dart/pub.dart
+++ b/packages/flutter_tools/lib/src/dart/pub.dart
@@ -127,6 +127,8 @@
     List<String> arguments, {
     String directory,
     @required io.Stdio stdio,
+    bool touchesPackageConfig = false,
+    bool generateSyntheticPackage = false,
   });
 }
 
@@ -324,6 +326,8 @@
     List<String> arguments, {
     String directory,
     @required io.Stdio stdio,
+    bool touchesPackageConfig = false,
+    bool generateSyntheticPackage = false,
   }) async {
     final io.Process process = await _processUtils.start(
       _pubCommand(arguments),
@@ -357,6 +361,23 @@
     if (code != 0) {
       throwToolExit('pub finished with exit code $code', exitCode: code);
     }
+
+    if (touchesPackageConfig) {
+      final File packageConfigFile = _fileSystem.file(
+        _fileSystem.path.join(directory, '.dart_tool', 'package_config.json'));
+      final Directory generatedDirectory = _fileSystem.directory(
+        _fileSystem.path.join(directory, '.dart_tool', 'flutter_gen'));
+      final File lastVersion = _fileSystem.file(
+        _fileSystem.path.join(directory, '.dart_tool', 'version'));
+      final File currentVersion = _fileSystem.file(
+        _fileSystem.path.join(Cache.flutterRoot, 'version'));
+        lastVersion.writeAsStringSync(currentVersion.readAsStringSync());
+      await _updatePackageConfig(
+        packageConfigFile,
+        generatedDirectory,
+        generateSyntheticPackage,
+      );
+    }
   }
 
   /// The command used for running pub.
diff --git a/packages/flutter_tools/test/commands.shard/permeable/packages_test.dart b/packages/flutter_tools/test/commands.shard/permeable/packages_test.dart
index 6c7aa33..57624fc 100644
--- a/packages/flutter_tools/test/commands.shard/permeable/packages_test.dart
+++ b/packages/flutter_tools/test/commands.shard/permeable/packages_test.dart
@@ -374,6 +374,7 @@
       expectDependenciesResolved(projectPath);
       expectZeroPluginsInjected(projectPath);
     }, overrides: <Type, Generator>{
+      Stdio: () => MockStdio()..stdout.terminalColumns = 80,
       Pub: () => Pub(
         fileSystem: globals.fs,
         logger: globals.logger,
diff --git a/packages/flutter_tools/test/src/throwing_pub.dart b/packages/flutter_tools/test/src/throwing_pub.dart
index 41a1509..de40136 100644
--- a/packages/flutter_tools/test/src/throwing_pub.dart
+++ b/packages/flutter_tools/test/src/throwing_pub.dart
@@ -36,7 +36,13 @@
   }
 
   @override
-  Future<void> interactively(List<String> arguments, {String directory, @required Stdio stdio,}) {
+  Future<void> interactively(
+    List<String> arguments, {
+    String directory,
+    @required Stdio stdio,
+    bool touchesPackageConfig = false,
+    bool generateSyntheticPackage = false,
+  }) {
     throw UnsupportedError('Attempted to invoke pub during test.');
   }
 }