Skip to content
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
125 changes: 89 additions & 36 deletions lib/src/core/dependencies/dependency_wirer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -95,22 +95,39 @@ class DependencyWirer {
static const zuraffaGitUrl = 'https://github.com/arrrrny/zuraffa';

/// Git source for the zorphy monorepo (contains `zorphy` and
/// `zorphy_annotation` sub-packages).
static const zorphyGitUrl = 'https://github.com/arrrrny/zorphy';
/// `zorphy_annotation` sub-packages). Must match the exact URL string used
/// by the zuraffa root pubspec (https://github.com/arrrrny/zorphy.git):
/// pub treats git sources as identical only when the URL string matches
/// verbatim, and a `.git`-vs-bare mismatch breaks version solving when
/// `zuraffa_flutter` pulls `zuraffa` transitively.
static const zorphyGitUrl = 'https://github.com/arrrrny/zorphy.git';

/// Default git ref — tracks the development branch which is where active
/// v6 work lands before merging to master.
static const defaultGitRef = 'development';

/// The analyzer version zuraffa pins (see root pubspec.yaml). Overriding
/// analyzer in downstream apps prevents version-conflict failures when
/// `dart pub get` resolves the transitive graph.
/// The analyzer version zuraffa pins in pure-Dart packages (see root
/// pubspec.yaml). Overriding analyzer in downstream apps prevents
/// version-conflict failures when `dart pub get` resolves the transitive
/// graph.
static const analyzerOverrideVersion = '14.1.0';

/// Flutter apps cannot use the [analyzerOverrideVersion] override: the
/// Flutter SDK pins `meta 1.18.0` while analyzer >=13.1.0 requires
/// `meta ^1.18.3`, so version solving always fails. These match
/// `zuraffa_flutter`'s own `dependency_overrides`
/// (zuraffa_flutter/pubspec.yaml): analyzer is capped at ^13.1.0 and meta
/// is overlaid with ^1.19.0 so the graph resolves under the Flutter SDK.
static const flutterAnalyzerOverrideVersion = '^13.1.0';
static const flutterMetaOverrideVersion = '^1.19.0';

/// Returns the standard zuraffa dependency set for the given project type.
///
/// [isFlutter] selects `zuraffa_flutter` + `flutter_lints` (Flutter apps)
/// versus `zuraffa` (pure Dart packages). All other entries are shared.
/// versus `zuraffa` (pure Dart packages), and picks the override set:
/// Flutter apps get the analyzer + meta overrides that match
/// `zuraffa_flutter`'s own pubspec, pure Dart packages pin analyzer
/// directly. All other entries are shared.
static List<DependencySpec> standardSet({required bool isFlutter}) {
return [
DependencySpec(
Expand All @@ -131,11 +148,23 @@ class DependencyWirer {
const DependencySpec(name: 'mocktail', kind: DependencyKind.dev),
if (isFlutter)
const DependencySpec(name: 'flutter_lints', kind: DependencyKind.dev),
const DependencySpec(
name: 'analyzer',
kind: DependencyKind.override,
version: analyzerOverrideVersion,
),
if (isFlutter) ...[
const DependencySpec(
name: 'analyzer',
kind: DependencyKind.override,
version: flutterAnalyzerOverrideVersion,
),
const DependencySpec(
name: 'meta',
kind: DependencyKind.override,
version: flutterMetaOverrideVersion,
),
] else
const DependencySpec(
name: 'analyzer',
kind: DependencyKind.override,
version: analyzerOverrideVersion,
),
];
}

Expand Down Expand Up @@ -168,7 +197,14 @@ class DependencyWirer {
case DependencyKind.dev:
return !devDeps.containsKey(spec.name);
case DependencyKind.override:
return !overrides.containsKey(spec.name);
if (!overrides.containsKey(spec.name)) {
return true; // missing entirely
}
// Key exists: check if the value matches the required version.
final existing = overrides[spec.name];
final existingStr = (existing is String ? existing : existing.toString()).trim();
final requiredStr = (spec.version ?? '').trim();
return existingStr != requiredStr; // stale if different
}
}).toList();
}
Expand All @@ -189,7 +225,9 @@ class DependencyWirer {
///
/// - If the `dependency_overrides:` section does not exist, it is appended.
/// - If it exists but [key] is absent, the entry is inserted under it.
/// - If [key] already exists, the content is returned unchanged (idempotent).
/// - If [key] already exists with the same [value], the content is returned
/// unchanged (idempotent). If the existing value differs, it is replaced
/// in place.
///
/// Pure function — does not perform I/O.
static String addOverrideToPubspec(
Expand Down Expand Up @@ -224,7 +262,14 @@ class DependencyWirer {
break;
}
if (line.startsWith(keyPrefix)) {
return content; // already present
// Key exists: check if the value matches.
final existingValue = line.substring(keyPrefix.length).trim();
if (existingValue == value) {
return content; // already has the correct value
}
// Value differs: replace the line.
lines[i] = ' $key: $value';
return lines.join('\n');
}
}

Expand Down Expand Up @@ -293,6 +338,33 @@ class DependencyWirer {
.where((s) => s.kind == DependencyKind.override)
.toList();

// --- dependency_overrides via direct pubspec edit ---
// Written BEFORE `pub add` so the version resolution that command
// triggers already sees the overrides. In Flutter apps the analyzer +
// meta overrides are what make the transitive graph resolvable in the
// first place, so they must be in the pubspec before anything resolves.
if (overrideSpecs.isNotEmpty) {
var newContent = pubspecFile.readAsStringSync();
for (final spec in overrideSpecs) {
newContent = addOverrideToPubspec(
newContent,
spec.name,
spec.version ?? '',
);
print(' ✅ Added override:${spec.name}=${spec.version}');
}
try {
await pubspecFile.writeAsString(newContent);
// Record overrides as added only after the write succeeds.
added.addAll(overrideSpecs.map((s) => s.name));
} catch (e) {
print(
' ⚠️ Failed to write dependency_overrides to pubspec.yaml: $e',
);
failed.addAll(overrideSpecs.map((s) => s.name));
}
}

Comment on lines +341 to +367

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Replace stale Flutter override values.

findMissing treats an override key as valid regardless of its value. addOverrideToPubspec also preserves that value. A Flutter project created with the prior analyzer: 14.1.0 override receives only meta, so it does not receive the required analyzer: ^13.1.0 override.

  • lib/src/core/dependencies/dependency_wirer.dart#L325-L351: detect mismatched override values and replace the stale value before pub add.
  • test/core/dependencies/dependency_wirer_test.dart#L265-L296: add a Flutter fixture with analyzer: 14.1.0 and assert that wiring identifies and updates it to ^13.1.0.
📍 Affects 2 files
  • lib/src/core/dependencies/dependency_wirer.dart#L325-L351 (this comment)
  • test/core/dependencies/dependency_wirer_test.dart#L265-L296
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lib/src/core/dependencies/dependency_wirer.dart` around lines 325 - 351,
Update dependency override handling in
lib/src/core/dependencies/dependency_wirer.dart lines 325-351 so
addOverrideToPubspec replaces an existing override when its value differs from
the required spec, ensuring stale values such as analyzer: 14.1.0 become ^13.1.0
before pub add. Add a Flutter fixture in
test/core/dependencies/dependency_wirer_test.dart lines 265-296 with the stale
analyzer override and assert wiring detects and updates it.

// --- regular / dev deps via `pub add` ---
// Flutter projects must use `flutter pub add`/`flutter pub get`: the
// standalone `dart` executable cannot resolve `sdk: flutter` deps.
Expand Down Expand Up @@ -320,28 +392,8 @@ class DependencyWirer {
}
}

// --- dependency_overrides via direct pubspec edit ---
// --- final re-resolve so the whole graph is consistent ---
if (overrideSpecs.isNotEmpty) {
var newContent = pubspecFile.readAsStringSync();
for (final spec in overrideSpecs) {
newContent = addOverrideToPubspec(
newContent,
spec.name,
spec.version ?? '',
);
print(' ✅ Added override:${spec.name}=${spec.version}');
}
try {
await pubspecFile.writeAsString(newContent);
// Record overrides as added only after the write succeeds.
added.addAll(overrideSpecs.map((s) => s.name));
} catch (e) {
print(
' ⚠️ Failed to write dependency_overrides to pubspec.yaml: $e',
);
failed.addAll(overrideSpecs.map((s) => s.name));
}
// Re-resolve so the override takes effect.
try {
final getResult = await Process.run(
pubExecutable,
Expand All @@ -352,7 +404,8 @@ class DependencyWirer {
final err = getResult.stderr.toString().trim();
if (err.isNotEmpty) {
print(
' ⚠️ $pubExecutable pub get reported issues after override edit:',
' ⚠️ $pubExecutable pub get reported issues after wiring '
'overrides ${overrideSpecs.map((s) => '${s.name}=${s.version}').join(', ')}:',
);
print(' ${err.split('\n').take(3).join('\n ')}');
}
Expand Down
3 changes: 2 additions & 1 deletion test/commands/setup_command_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,8 @@ dev_dependencies:
mocktail: ^1.0.4
flutter_lints: ^6.0.0
dependency_overrides:
analyzer: 14.1.0
analyzer: ^13.1.0
meta: ^1.19.0
''';
final missing = DependencyWirer.findMissing(fullPubspec, isFlutter: true);
expect(missing, isEmpty);
Expand Down
Loading
Loading