MCPcopy
hub / github.com/garrytan/gstack / harvest

Method harvest

lib/worktree.ts:152–212  ·  view source on GitHub ↗

Harvest changes from a worktree. Returns null if clean or on error.

(testName: string)

Source from the content-addressed store, hash-verified

150
151 /** Harvest changes from a worktree. Returns null if clean or on error. */
152 harvest(testName: string): HarvestResult | null {
153 const info = this.active.get(testName);
154 if (!info) return null;
155
156 try {
157 // Check if worktree directory still exists (agent may have deleted it)
158 if (!fs.existsSync(info.path)) {
159 process.stderr.write(` HARVEST [${testName}]: worktree dir deleted, skipping\n`);
160 return null;
161 }
162
163 // Stage everything including untracked files
164 git(['-C', info.path, 'add', '-A'], info.path, true);
165
166 // Get diff against original SHA (captures both committed and uncommitted changes)
167 const patch = git(['-C', info.path, 'diff', info.originalSha, '--cached'], info.path, true);
168
169 if (!patch) return null;
170
171 // Get diff stat for human-readable output
172 const diffStat = git(['-C', info.path, 'diff', info.originalSha, '--cached', '--stat'], info.path, true);
173
174 // Get changed file names
175 const nameOnly = git(['-C', info.path, 'diff', info.originalSha, '--cached', '--name-only'], info.path, true);
176 const changedFiles = nameOnly.split('\n').filter(Boolean);
177
178 // Dedup check
179 const hash = crypto.createHash('sha256').update(patch).digest('hex');
180 const dedupIndex = loadDedupIndex();
181 const isDuplicate = hash in dedupIndex.hashes;
182
183 let patchPath = '';
184
185 if (!isDuplicate) {
186 // Save patch
187 const harvestDir = path.join(os.homedir(), '.gstack-dev', 'harvests', this.runId);
188 fs.mkdirSync(harvestDir, { recursive: true });
189 patchPath = path.join(harvestDir, `${testName}.patch`);
190 fs.writeFileSync(patchPath, patch);
191
192 // Update dedup index
193 dedupIndex.hashes[hash] = this.runId;
194 saveDedupIndex(dedupIndex);
195 }
196
197 const result: HarvestResult = {
198 testName,
199 worktreePath: info.path,
200 diffStat,
201 patchPath,
202 changedFiles,
203 isDuplicate,
204 };
205
206 this.harvestResults.push(result);
207 return result;
208 } catch (err) {
209 process.stderr.write(` HARVEST [${testName}]: error — ${err}\n`);

Callers 2

worktree.test.tsFile · 0.80
harvestAndCleanupFunction · 0.80

Calls 5

loadDedupIndexFunction · 0.85
saveDedupIndexFunction · 0.85
gitFunction · 0.70
getMethod · 0.45
pushMethod · 0.45

Tested by

no test coverage detected