Address constructor

Address({
  1. String? project,
  2. String? space,
  3. String? worktree,
  4. String? plugin,
  5. List<String> segments = const [],
  6. Map<String, String> axes = const {},
})

space defaults to the one a worktree lives in, so the many call sites that name a worktree and a plugin read exactly as they did before the space segment existed.

Implementation

Address({
  this.project,
  String? space,
  this.worktree,
  this.plugin,
  List<String> segments = const [],
  Map<String, String> axes = const {},
}) : space = space ?? (worktree != null ? worktreesSpace : null),
     segments = List.unmodifiable(segments),
     axes = Map.unmodifiable({
       for (var key in axes.keys.toList()..sort()) key: axes[key]!,
     }) {
  if (project != null && project!.isEmpty) {
    throw ArgumentError.value(project, 'project', 'Must not be empty.');
  }
  if (this.space != null && this.space!.isEmpty) {
    throw ArgumentError.value(space, 'space', 'Must not be empty.');
  }
  if (worktree != null && this.space != worktreesSpace) {
    throw ArgumentError.value(
      space,
      'space',
      'A worktree lives in the $worktreesSpace space; no other space has one.',
    );
  }
  if (worktree != null && worktree!.isEmpty) {
    throw ArgumentError.value(worktree, 'worktree', 'Must not be empty.');
  }
  if (worktree == null && plugin != null) {
    throw ArgumentError.value(
      plugin,
      'plugin',
      'A plugin is reached through a worktree; an address naming one must '
          'name a worktree.',
    );
  }
  if (plugin != null && plugin!.isEmpty) {
    throw ArgumentError.value(plugin, 'plugin', 'Must not be empty.');
  }
  if (plugin == null && this.segments.isNotEmpty) {
    throw ArgumentError.value(
      segments,
      'segments',
      'Segments belong to a plugin; an address with segments must name one.',
    );
  }
}