WorkingSet.java
package network.ike.workspace;
import java.nio.file.Path;
import java.util.List;
/**
* The co-located set of git working trees a working-tree workspace
* operation acts on — one repository for a single repo, or the subprojects
* plus the workspace root for a workspace (IKE-Network/ike-issues#609,
* under the console/engine boundary, #601).
*
* <p>A working set is resolved from context by {@link WorkingSetResolver}:
* a single repository is a working set of one; a {@code workspace.yaml}
* declares a larger one. Working-tree verbs — commit, push, sync, branch,
* fork, switch — act on each {@link Member}; the {@link #manifest()}, when
* present, carries the workspace metadata.
*
* <p>The workspace root (aggregator) is a first-class {@link Member}, not an
* orchestrator standing outside the set: it is branched, version-qualified,
* committed, and tagged alongside the subprojects. Each member therefore
* carries a {@link Member.Kind} so reports and lifecycle goals can include the
* aggregator and special-case it where its role differs (#764).
*
* <p>This is the working-set half of the scope-resolution layer; the
* dependency-ordered <em>artifact cohort</em> that release-style verbs need
* is modelled separately (ike-issues#610).
*
* @param root the primary directory — the workspace root, or the single
* repository
* @param manifest the {@code workspace.yaml} path, or {@code null} for a
* single-repository working set
* @param baseName the working set's identity for derived names — the base for
* sibling directories ({@code <baseName>-<feature>}): the
* manifest {@code workspace-root:} {@code artifactId} when
* present, otherwise the root directory name
* @param members every git working tree in the set, in a deterministic
* order: the declared subprojects followed by the workspace
* root (a single-repository working set has the one repo as
* its sole member). The workspace root is the member whose
* {@link Member#directory()} equals {@link #root()} and whose
* {@link Member#kind()} is {@link Member.Kind#AGGREGATOR}.
*/
public record WorkingSet(Path root, Path manifest, String baseName,
List<Member> members) {
/**
* Whether this working set is backed by a {@code workspace.yaml}.
*
* @return {@code true} for a workspace, {@code false} for a single repo
*/
public boolean isWorkspace() {
return manifest != null;
}
/**
* Whether this is a single-repository working set — a working set of one.
*
* @return {@code true} for a single repository
*/
public boolean isSingleRepo() {
return manifest == null;
}
/**
* One git working tree in a {@link WorkingSet}.
*
* @param name the subproject name, or the directory name for the
* workspace root and for a single repository
* @param directory the git working tree's directory
* @param kind whether this member is a declared subproject or the
* workspace root (aggregator)
*/
public record Member(String name, Path directory, Kind kind) {
/**
* The role a {@link Member} plays in its {@link WorkingSet}.
* "Subproject" is a member <em>kind</em>, never the organizing unit —
* the working set is the unit, and the aggregator is one of its
* members (#764).
*/
public enum Kind {
/** A declared subproject of a workspace. */
SUBPROJECT,
/**
* The workspace root that aggregates the subprojects — and, for a
* single-repository working set, the sole member, which is the
* root of its own trivial set.
*/
AGGREGATOR
}
/**
* Create a {@link Kind#SUBPROJECT} member.
*
* @param name the subproject name
* @param directory the subproject's git working tree
* @return a subproject member
*/
public static Member subproject(String name, Path directory) {
return new Member(name, directory, Kind.SUBPROJECT);
}
/**
* Create a {@link Kind#AGGREGATOR} member.
*
* @param name the directory name of the workspace root (or single
* repository)
* @param directory the workspace root's git working tree
* @return an aggregator member
*/
public static Member aggregator(String name, Path directory) {
return new Member(name, directory, Kind.AGGREGATOR);
}
/**
* Whether this member is the workspace root (aggregator).
*
* @return {@code true} if {@link #kind()} is {@link Kind#AGGREGATOR}
*/
public boolean isAggregator() {
return kind == Kind.AGGREGATOR;
}
}
}