Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New command workspace list #4378

Merged
merged 6 commits into from
Sep 12, 2024
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
95 changes: 16 additions & 79 deletions lib/src/command/outdated.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

import 'dart:async';
import 'dart:convert';
import 'dart:math';

import 'package:collection/collection.dart' show IterableExtension;
import 'package:path/path.dart' as p;
Expand All @@ -15,6 +14,7 @@ import '../entrypoint.dart';
import '../io.dart';
import '../lock_file.dart';
import '../log.dart' as log;
import '../log.dart';
import '../package.dart';
import '../package_name.dart';
import '../pubspec.dart';
Expand Down Expand Up @@ -552,8 +552,8 @@ Future<void> _outputHuman(
final markedRows =
Map.fromIterables(rows, await mode.markVersionDetails(rows));

List<_FormattedString> formatted(_PackageDetails package) => [
_FormattedString(package.name),
List<FormattedString> formatted(_PackageDetails package) => [
FormattedString(package.name),
...markedRows[package]!.map((m) => m.toHuman()),
];

Expand All @@ -575,64 +575,42 @@ Future<void> _outputHuman(
final devTransitiveRows =
rows.where(hasKind(_DependencyKind.devTransitive)).map(formatted);

final formattedRows = <List<_FormattedString>>[
final formattedRows = <List<FormattedString>>[
['Package Name', 'Current', 'Upgradable', 'Resolvable', 'Latest']
.map((s) => _format(s, log.bold))
.map((s) => format(s, log.bold))
.toList(),
if (hasDirectDependencies) ...[
[
if (directRows.isEmpty)
_format('\ndirect dependencies: ${mode.allGood}', log.bold)
format('\ndirect dependencies: ${mode.allGood}', log.bold)
else
_format('\ndirect dependencies:', log.bold),
format('\ndirect dependencies:', log.bold),
],
...directRows,
],
if (includeDevDependencies && hasDevDependencies) ...[
[
if (devRows.isEmpty)
_format('\ndev_dependencies: ${mode.allGood}', log.bold)
format('\ndev_dependencies: ${mode.allGood}', log.bold)
else
_format('\ndev_dependencies:', log.bold),
format('\ndev_dependencies:', log.bold),
],
...devRows,
],
if (showTransitiveDependencies) ...[
if (transitiveRows.isNotEmpty)
[_format('\ntransitive dependencies:', log.bold)],
[format('\ntransitive dependencies:', log.bold)],
...transitiveRows,
if (includeDevDependencies) ...[
if (devTransitiveRows.isNotEmpty)
[_format('\ntransitive dev_dependencies:', log.bold)],
[format('\ntransitive dev_dependencies:', log.bold)],
...devTransitiveRows,
],
],
];

final columnWidths = <int, int>{};
for (var i = 0; i < formattedRows.length; i++) {
if (formattedRows[i].length > 1) {
for (var j = 0; j < formattedRows[i].length; j++) {
final currentMaxWidth = columnWidths[j] ?? 0;
columnWidths[j] = max(
formattedRows[i][j].computeLength(useColors: useColors),
currentMaxWidth,
);
}
}
}

for (final row in formattedRows) {
final b = StringBuffer();
for (var j = 0; j < row.length; j++) {
b.write(row[j].formatted(useColors: useColors));
b.write(
' ' *
((columnWidths[j]! + 2) -
row[j].computeLength(useColors: useColors)),
);
}
log.message(b.toString());
for (final line in log.renderTable(formattedRows, useColors)) {
log.message(line);
}

final upgradable = rows.where(
Expand Down Expand Up @@ -1016,16 +994,8 @@ enum _DependencyKind {
devTransitive,
}

_FormattedString _format(
String value,
String Function(String) format, {
String? prefix = '',
}) {
return _FormattedString(value, format: format, prefix: prefix);
}

abstract class _Details {
_FormattedString toHuman();
FormattedString toHuman();
Object? toJson();
}

Expand All @@ -1035,7 +1005,7 @@ class _SimpleDetails implements _Details {
_SimpleDetails(this.details);

@override
_FormattedString toHuman() => _FormattedString(details);
FormattedString toHuman() => FormattedString(details);

@override
Object? toJson() => null;
Expand All @@ -1060,7 +1030,7 @@ class _MarkedVersionDetails implements _Details {
_jsonExplanation = jsonExplanation;

@override
_FormattedString toHuman() => _FormattedString(
FormattedString toHuman() => FormattedString(
_versionDetails?.describe ?? '-',
format: _format,
prefix: _prefix,
Expand All @@ -1078,39 +1048,6 @@ class _MarkedVersionDetails implements _Details {
}
}

class _FormattedString {
final String value;

/// Should apply the ansi codes to present this string.
final String Function(String) _format;

/// A prefix for marking this string if colors are not used.
final String _prefix;

final String _suffix;

_FormattedString(
this.value, {
String Function(String)? format,
String? prefix,
String? suffix,
}) : _format = format ?? _noFormat,
_prefix = prefix ?? '',
_suffix = suffix ?? '';

String formatted({required bool useColors}) {
return useColors
? _format(_prefix + value + _suffix)
: _prefix + value + _suffix;
}

int computeLength({required bool? useColors}) {
return _prefix.length + value.length + _suffix.length;
}

static String _noFormat(String x) => x;
}

/// Whether the package [name] is overridden anywhere in the workspace rooted at
/// [workspaceRoot].
bool hasOverride(Package workspaceRoot, String name) {
Expand Down
18 changes: 18 additions & 0 deletions lib/src/command/workspace.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file
// 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 '../command.dart';
import 'workspace_list.dart';

class WorkspaceCommand extends PubCommand {
@override
String get description => 'Work with the pub workspace.';

@override
String get name => 'workspace';

WorkspaceCommand() {
addSubcommand(WorkspaceListCommand());
}
}
63 changes: 63 additions & 0 deletions lib/src/command/workspace_list.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file
// 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 'dart:convert';

import 'package:path/path.dart' as p;

import '../command.dart';
import '../log.dart';
import '../utils.dart';

class WorkspaceListCommand extends PubCommand {
@override
String get description =>
'List all packages in the workspace, and their directory';

@override
String get name => 'list';

WorkspaceListCommand() {
argParser.addFlag(
'json',
negatable: false,
help: 'output information in a json format',
);
}

@override
void runProtected() {
if (argResults.flag('json')) {
message(
const JsonEncoder.withIndent(' ').convert({
'packages': [
...entrypoint.workspaceRoot.transitiveWorkspace.map(
(package) => {
'name': package.name,
'path': p.canonicalize(package.dir),
},
),
],
}),
);
} else {
for (final line in renderTable(
[
[format('Package', bold), format('Path', bold)],
for (final package in entrypoint.workspaceRoot.transitiveWorkspace)
[
format(package.name, (x) => x),
format(
'${p.relative(p.absolute(package.dir))}${p.separator}',
(x) => x,
),
],
],
canUseAnsiCodes,
)) {
message(line);
}
}
}
}
2 changes: 2 additions & 0 deletions lib/src/command_runner.dart
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import 'command/unpack.dart';
import 'command/upgrade.dart';
import 'command/uploader.dart';
import 'command/version.dart';
import 'command/workspace.dart';
import 'exit_codes.dart' as exit_codes;
import 'git.dart' as git;
import 'io.dart';
Expand Down Expand Up @@ -156,6 +157,7 @@ class PubCommandRunner extends CommandRunner<int> implements PubTopLevel {
addCommand(LoginCommand());
addCommand(LogoutCommand());
addCommand(VersionCommand());
addCommand(WorkspaceCommand());
addCommand(TokenCommand());
}

Expand Down
78 changes: 78 additions & 0 deletions lib/src/log.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ library;
import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'dart:math';

import 'package:args/command_runner.dart';
import 'package:path/path.dart' as p;
Expand Down Expand Up @@ -635,3 +636,80 @@ class _JsonLogger {
stdout.writeln(jsonEncode(message));
}
}

/// Represents a string and its highlighting separately, such that we can
/// compute the displayed length.
class FormattedString {
final String value;

/// Should apply the ansi codes to present this string.
final String Function(String) _format;

/// A prefix for marking this string if colors are not used.
final String _prefix;

final String _suffix;

FormattedString(
this.value, {
String Function(String)? format,
String? prefix,
String? suffix,
}) : _format = format ?? _noFormat,
_prefix = prefix ?? '',
_suffix = suffix ?? '';

String formatted({required bool useColors}) {
return useColors
? _format(_prefix + value + _suffix)
: _prefix + value + _suffix;
}

int computeLength({required bool? useColors}) {
return _prefix.length + value.length + _suffix.length;
}

static String _noFormat(String x) => x;
}

FormattedString format(
String value,
String Function(String) format, {
String? prefix = '',
}) =>
FormattedString(value, format: format, prefix: prefix);

/// Formats a table of [rows], inserting enough spaces to make columns line up.
List<String> renderTable(
List<List<FormattedString>> rows,
bool useColors,
) {
// Compute the width of each column by taking the max across all rows.
final columnWidths = <int, int>{};
for (var i = 0; i < rows.length; i++) {
if (rows[i].length > 1) {
for (var j = 0; j < rows[i].length; j++) {
final currentMaxWidth = columnWidths[j] ?? 0;
columnWidths[j] = max(
rows[i][j].computeLength(useColors: useColors),
currentMaxWidth,
);
}
}
}

final result = <String>[];
for (final row in rows) {
final b = StringBuffer();
for (var j = 0; j < row.length; j++) {
b.write(row[j].formatted(useColors: useColors));
b.write(
' ' *
((columnWidths[j]! + 2) -
row[j].computeLength(useColors: useColors)),
);
}
result.add(b.toString());
}
return result;
}
2 changes: 2 additions & 0 deletions lib/src/pub_embeddable_command.dart
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import 'command/token.dart';
import 'command/unpack.dart';
import 'command/upgrade.dart';
import 'command/uploader.dart';
import 'command/workspace.dart';
import 'log.dart' as log;
import 'log.dart';
import 'utils.dart';
Expand Down Expand Up @@ -86,6 +87,7 @@ class PubEmbeddableCommand extends PubCommand implements PubTopLevel {
addSubcommand(LoginCommand());
addSubcommand(LogoutCommand());
addSubcommand(TokenCommand());
addSubcommand(WorkspaceCommand());
}

@override
Expand Down
Loading
Loading