Skip to content

Commit b483e9d

Browse files
Refactor shared worktree cleanup primitives (#773)
* refactor: share worktree cleanup primitives * fix: satisfy cleanup primitive lint --------- Co-authored-by: homeboy-ci[bot] <266378653+homeboy-ci[bot]@users.noreply.github.com>
1 parent c7d028b commit b483e9d

5 files changed

Lines changed: 218 additions & 158 deletions

File tree

inc/Workspace/Workspace.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
require_once __DIR__ . '/WorkspaceRepositoryLifecycle.php';
2525
require_once __DIR__ . '/WorkspaceRowTriage.php';
2626
require_once __DIR__ . '/WorkspaceWorktreeLifecycle.php';
27+
require_once __DIR__ . '/WorktreeAgeFilter.php';
28+
require_once __DIR__ . '/WorktreeCleanupSignal.php';
2729
require_once __DIR__ . '/WorkspaceWorktreeCleanupEngine.php';
2830
require_once __DIR__ . '/WorkspaceWorktreeInventoryCleanup.php';
2931
require_once __DIR__ . '/WorkspaceWorktreeEmergencyCleanup.php';

inc/Workspace/WorkspaceWorktreeCleanupEngine.php

Lines changed: 26 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -124,16 +124,7 @@ public function worktree_cleanup_merged( array $opts = array() ): array|\WP_Erro
124124
return $duration_seconds;
125125
}
126126

127-
$threshold_ts = time() - $duration_seconds;
128-
$age_filter = array(
129-
'type' => 'older_than',
130-
'older_than' => $older_than,
131-
'duration_seconds' => $duration_seconds,
132-
'threshold' => gmdate('c', $threshold_ts),
133-
'threshold_unix' => $threshold_ts,
134-
'excluded' => 0,
135-
'unknown_age' => 0,
136-
);
127+
$age_filter = WorktreeAgeFilter::build($older_than, $duration_seconds);
137128
}
138129

139130
$listing = $this->worktree_list(
@@ -482,21 +473,8 @@ public function worktree_cleanup_merged( array $opts = array() ): array|\WP_Erro
482473
$fetched[ $repo ] = true;
483474
}
484475

485-
$signal = null;
486-
if ( is_array($metadata) && WorktreeContextInjector::has_cleanup_signal($metadata) ) {
487-
$signal = array(
488-
'signal' => 'cleanup_eligible',
489-
'reason' => 'worktree finalized or explicitly marked cleanup_eligible',
490-
);
491-
if ( ! empty($metadata['pr_url']) ) {
492-
$signal['pr_url'] = (string) $metadata['pr_url'];
493-
}
494-
} elseif ( $include_repaired_metadata && is_array($metadata) && ! empty($metadata['metadata_repaired']) ) {
495-
$signal = array(
496-
'signal' => 'repaired_metadata',
497-
'reason' => 'operator-approved cleanup of repaired metadata',
498-
);
499-
} else {
476+
$signal = is_array($metadata) ? WorktreeCleanupSignal::from_metadata($metadata, $include_repaired_metadata) : null;
477+
if ( null === $signal ) {
500478
$signal = $this->detect_merge_signal($primary_path, $repo, $branch, $skip_github, $github_cache);
501479
}
502480
if ( null === $signal ) {
@@ -559,58 +537,38 @@ public function worktree_cleanup_merged( array $opts = array() ): array|\WP_Erro
559537

560538
$age_decision = null;
561539
if ( null !== $age_filter ) {
562-
$created_ts = is_string($created_at) && '' !== $created_at ? strtotime($created_at) : false;
563-
if ( false === $created_ts ) {
564-
++$age_filter['unknown_age'];
540+
$age_decision = WorktreeAgeFilter::decide($created_at, $age_filter);
541+
if ( 'unknown_age' === $age_decision['decision'] ) {
565542
$skipped[] = array_merge(
566543
array(
567-
'handle' => $handle,
568-
'repo' => $repo,
569-
'branch' => $branch,
570-
'path' => $wt_path,
571-
'reason_code' => 'unknown_age',
572-
'reason' => 'missing or invalid created_at metadata - age filter cannot decide safely',
573-
'created_at' => $created_at,
574-
'metadata' => $metadata,
575-
'age_filter' => array(
576-
'type' => 'older_than',
577-
'older_than' => $age_filter['older_than'],
578-
'threshold' => $age_filter['threshold'],
579-
'decision' => 'unknown_age',
580-
),
581-
), $disk_fields
544+
'handle' => $handle,
545+
'repo' => $repo,
546+
'branch' => $branch,
547+
'path' => $wt_path,
548+
'created_at' => $created_at,
549+
'metadata' => $metadata,
550+
),
551+
WorktreeAgeFilter::skip_fields($age_decision),
552+
$disk_fields
582553
);
583554
continue;
584555
}
585556

586-
$age_seconds = time() - $created_ts;
587-
$age_decision = array(
588-
'type' => 'older_than',
589-
'older_than' => $age_filter['older_than'],
590-
'threshold' => $age_filter['threshold'],
591-
'created_at' => $created_at,
592-
'age_seconds' => $age_seconds,
593-
);
594-
595-
if ( $created_ts > $age_filter['threshold_unix'] ) {
596-
++$age_filter['excluded'];
557+
if ( 'excluded' === $age_decision['decision'] ) {
597558
$skipped[] = array_merge(
598559
array(
599-
'handle' => $handle,
600-
'repo' => $repo,
601-
'branch' => $branch,
602-
'path' => $wt_path,
603-
'reason_code' => 'age_filter',
604-
'reason' => sprintf('created_at %s is newer than --older-than=%s threshold %s', $created_at, $age_filter['older_than'], $age_filter['threshold']),
605-
'created_at' => $created_at,
606-
'metadata' => $metadata,
607-
'age_filter' => array_merge($age_decision, array( 'decision' => 'excluded' )),
608-
), $disk_fields
560+
'handle' => $handle,
561+
'repo' => $repo,
562+
'branch' => $branch,
563+
'path' => $wt_path,
564+
'created_at' => $created_at,
565+
'metadata' => $metadata,
566+
),
567+
WorktreeAgeFilter::skip_fields($age_decision),
568+
$disk_fields
609569
);
610570
continue;
611571
}
612-
613-
$age_decision['decision'] = 'included';
614572
}
615573

616574
$candidate = array_merge(
@@ -620,18 +578,14 @@ public function worktree_cleanup_merged( array $opts = array() ): array|\WP_Erro
620578
'branch' => $branch,
621579
'path' => $wt_path,
622580
'dirty' => $dirty_count,
623-
'signal' => $signal['signal'],
624-
'reason_code' => $signal['signal'],
625-
'reason' => $signal['reason'],
626581
'cleanup_reasons' => array_values(array_filter(array( $signal['signal'], $signal['reason'] ))),
627-
'pr_url' => $signal['pr_url'] ?? null,
628582
'created_at' => $created_at,
629583
'liveness' => $liveness,
630584
'metadata' => $metadata,
631-
), $disk_fields
585+
), WorktreeCleanupSignal::candidate_fields($signal, true), $disk_fields
632586
);
633587
if ( null !== $age_decision ) {
634-
$candidate['age_filter'] = $age_decision;
588+
$candidate['age_filter'] = $age_decision['age_filter'];
635589
}
636590
$candidates[] = $candidate;
637591
}

inc/Workspace/WorkspaceWorktreeInventoryCleanup.php

Lines changed: 27 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -36,16 +36,7 @@ private function worktree_cleanup_inventory_only( string $older_than, string $so
3636
return $duration_seconds;
3737
}
3838

39-
$threshold_ts = time() - $duration_seconds;
40-
$age_filter = array(
41-
'type' => 'older_than',
42-
'older_than' => $older_than,
43-
'duration_seconds' => $duration_seconds,
44-
'threshold' => gmdate('c', $threshold_ts),
45-
'threshold_unix' => $threshold_ts,
46-
'excluded' => 0,
47-
'unknown_age' => 0,
48-
);
39+
$age_filter = WorktreeAgeFilter::build($older_than, $duration_seconds);
4940
}
5041

5142
$candidates = array();
@@ -117,56 +108,33 @@ private function worktree_cleanup_inventory_only( string $older_than, string $so
117108
if ( $include_repaired_metadata && $repaired ) {
118109
$age_decision = null;
119110
if ( null !== $age_filter ) {
120-
$created_ts = is_string($created_at) && '' !== $created_at ? strtotime($created_at) : false;
121-
if ( false === $created_ts ) {
122-
++$age_filter['unknown_age'];
111+
$age_decision = WorktreeAgeFilter::decide($created_at, $age_filter);
112+
if ( 'unknown_age' === $age_decision['decision'] ) {
123113
$skipped[] = array_merge(
124-
$base_row, array(
125-
'reason_code' => 'unknown_age',
126-
'reason' => 'missing or invalid created_at metadata - age filter cannot decide safely',
127-
'age_filter' => array(
128-
'type' => 'older_than',
129-
'older_than' => $age_filter['older_than'],
130-
'threshold' => $age_filter['threshold'],
131-
'decision' => 'unknown_age',
132-
),
133-
)
114+
$base_row,
115+
WorktreeAgeFilter::skip_fields($age_decision)
134116
);
135117
continue;
136118
}
137119

138-
$age_decision = array(
139-
'type' => 'older_than',
140-
'older_than' => $age_filter['older_than'],
141-
'threshold' => $age_filter['threshold'],
142-
'created_at' => $created_at,
143-
'age_seconds' => time() - $created_ts,
144-
);
145-
if ( $created_ts > $age_filter['threshold_unix'] ) {
146-
++$age_filter['excluded'];
120+
if ( 'excluded' === $age_decision['decision'] ) {
147121
$skipped[] = array_merge(
148-
$base_row, array(
149-
'reason_code' => 'age_filter',
150-
'reason' => sprintf('created_at %s is newer than --older-than=%s threshold %s', $created_at, $age_filter['older_than'], $age_filter['threshold']),
151-
'age_filter' => array_merge($age_decision, array( 'decision' => 'excluded' )),
152-
)
122+
$base_row,
123+
WorktreeAgeFilter::skip_fields($age_decision)
153124
);
154125
continue;
155126
}
156-
$age_decision['decision'] = 'included';
157127
}
158128

129+
$signal = WorktreeCleanupSignal::from_metadata($metadata, true);
159130
$candidate = array_merge(
160131
$base_row, array(
161132
'dirty' => 0,
162-
'signal' => 'repaired_metadata',
163-
'reason_code' => 'repaired_metadata',
164-
'reason' => 'operator-approved cleanup of repaired metadata',
165133
'repair_status' => 'repaired_metadata',
166-
)
134+
), WorktreeCleanupSignal::candidate_fields($signal ?? array())
167135
);
168136
if ( null !== $age_decision ) {
169-
$candidate['age_filter'] = $age_decision;
137+
$candidate['age_filter'] = $age_decision['age_filter'];
170138
}
171139
$candidates[] = $candidate;
172140
continue;
@@ -181,63 +149,36 @@ private function worktree_cleanup_inventory_only( string $older_than, string $so
181149
continue;
182150
}
183151

152+
$age_decision = null;
184153
if ( null !== $age_filter ) {
185-
$created_ts = is_string($created_at) && '' !== $created_at ? strtotime($created_at) : false;
186-
if ( false === $created_ts ) {
187-
++$age_filter['unknown_age'];
154+
$age_decision = WorktreeAgeFilter::decide($created_at, $age_filter);
155+
if ( 'unknown_age' === $age_decision['decision'] ) {
188156
$skipped[] = array_merge(
189-
$base_row, array(
190-
'reason_code' => 'unknown_age',
191-
'reason' => 'missing or invalid created_at metadata - age filter cannot decide safely',
192-
'age_filter' => array(
193-
'type' => 'older_than',
194-
'older_than' => $age_filter['older_than'],
195-
'threshold' => $age_filter['threshold'],
196-
'decision' => 'unknown_age',
197-
),
198-
)
157+
$base_row,
158+
WorktreeAgeFilter::skip_fields($age_decision)
199159
);
200160
continue;
201161
}
202162

203-
if ( $created_ts > $age_filter['threshold_unix'] ) {
204-
++$age_filter['excluded'];
163+
if ( 'excluded' === $age_decision['decision'] ) {
205164
$skipped[] = array_merge(
206-
$base_row, array(
207-
'reason_code' => 'age_filter',
208-
'reason' => sprintf('created_at %s is newer than --older-than=%s threshold %s', $created_at, $age_filter['older_than'], $age_filter['threshold']),
209-
'age_filter' => array(
210-
'type' => 'older_than',
211-
'older_than' => $age_filter['older_than'],
212-
'threshold' => $age_filter['threshold'],
213-
'created_at' => $created_at,
214-
'age_seconds' => time() - $created_ts,
215-
'decision' => 'excluded',
216-
),
217-
)
165+
$base_row,
166+
WorktreeAgeFilter::skip_fields($age_decision)
218167
);
219168
continue;
220169
}
221170
}
222171

172+
$signal = WorktreeCleanupSignal::from_metadata($metadata);
223173
$candidate = array_merge(
224-
$base_row, array(
225-
'dirty' => 0,
226-
'signal' => 'cleanup_eligible',
227-
'reason_code' => 'cleanup_eligible',
228-
'reason' => 'worktree finalized or explicitly marked cleanup_eligible',
229-
'pr_url' => $metadata['pr_url'] ?? null,
230-
)
174+
$base_row,
175+
array(
176+
'dirty' => 0,
177+
),
178+
WorktreeCleanupSignal::candidate_fields($signal ?? array(), true)
231179
);
232-
if ( null !== $age_filter && is_string($created_at) && '' !== $created_at ) {
233-
$candidate['age_filter'] = array(
234-
'type' => 'older_than',
235-
'older_than' => $age_filter['older_than'],
236-
'threshold' => $age_filter['threshold'],
237-
'created_at' => $created_at,
238-
'age_seconds' => time() - (int) strtotime($created_at),
239-
'decision' => 'included',
240-
);
180+
if ( null !== $age_decision ) {
181+
$candidate['age_filter'] = $age_decision['age_filter'];
241182
}
242183

243184
$candidates[] = $candidate;

0 commit comments

Comments
 (0)