* takt: github-issue-395-add-pull-from * ci: trigger CI checks * fix: taskDiffActions のコンフリクトマーカーを解消 origin/main でリネームされた「Merge from root」ラベル(PR #394)と、 このPR (#395) で追加した「Pull from remote」行を統合する。 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * ci: trigger CI checks --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: masanobu-naruse <m_naruse@codmon.co.jp> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
96 lines
3.0 KiB
TypeScript
96 lines
3.0 KiB
TypeScript
import { execFileSync } from 'node:child_process';
|
|
import { success, error as logError } from '../../../shared/ui/index.js';
|
|
import { createLogger, getErrorMessage } from '../../../shared/utils/index.js';
|
|
import {
|
|
type BranchActionTarget,
|
|
resolveTargetBranch,
|
|
validateWorktreeTarget,
|
|
pushWorktreeToOrigin,
|
|
} from './taskActionTarget.js';
|
|
|
|
const log = createLogger('list-tasks');
|
|
|
|
const TEMP_REMOTE_NAME = 'origin';
|
|
|
|
function getOriginUrl(projectDir: string): string {
|
|
return execFileSync(
|
|
'git', ['config', '--get', 'remote.origin.url'],
|
|
{ cwd: projectDir, encoding: 'utf-8', stdio: 'pipe' },
|
|
).trim();
|
|
}
|
|
|
|
export function pullFromRemote(
|
|
projectDir: string,
|
|
target: BranchActionTarget,
|
|
): boolean {
|
|
if (!validateWorktreeTarget(target, 'Pull')) {
|
|
return false;
|
|
}
|
|
const worktreePath = target.worktreePath;
|
|
const branch = resolveTargetBranch(target);
|
|
|
|
let originUrl: string;
|
|
try {
|
|
originUrl = getOriginUrl(projectDir);
|
|
} catch (err) {
|
|
logError(`Failed to get origin URL: ${getErrorMessage(err)}`);
|
|
log.error('getOriginUrl failed', { projectDir, error: getErrorMessage(err) });
|
|
return false;
|
|
}
|
|
log.info('Retrieved origin URL from root repo', { projectDir, originUrl });
|
|
|
|
try {
|
|
execFileSync('git', ['remote', 'add', TEMP_REMOTE_NAME, originUrl], {
|
|
cwd: worktreePath,
|
|
encoding: 'utf-8',
|
|
stdio: 'pipe',
|
|
});
|
|
log.info('Added temporary origin remote', { worktreePath, originUrl });
|
|
|
|
try {
|
|
execFileSync('git', ['pull', '--ff-only', TEMP_REMOTE_NAME, branch], {
|
|
cwd: worktreePath,
|
|
encoding: 'utf-8',
|
|
stdio: 'pipe',
|
|
});
|
|
log.info('Pull succeeded', { worktreePath, branch });
|
|
} catch (err) {
|
|
const msg = getErrorMessage(err);
|
|
logError(`Pull failed (not fast-forwardable?): ${msg}`);
|
|
logError('If the branch has diverged, use "Sync with root" instead.');
|
|
log.error('git pull --ff-only failed', { worktreePath, branch, error: msg });
|
|
return false;
|
|
}
|
|
} catch (err) {
|
|
logError(`Failed to add temporary remote: ${getErrorMessage(err)}`);
|
|
log.error('git remote add failed', { worktreePath, originUrl, error: getErrorMessage(err) });
|
|
return false;
|
|
} finally {
|
|
removeTemporaryRemote(worktreePath);
|
|
}
|
|
|
|
try {
|
|
pushWorktreeToOrigin(worktreePath, projectDir, branch);
|
|
} catch (err) {
|
|
logError(`Push failed after pull: ${getErrorMessage(err)}`);
|
|
log.error('pushWorktreeToOrigin failed', { worktreePath, projectDir, branch, error: getErrorMessage(err) });
|
|
return false;
|
|
}
|
|
success('Pulled & pushed.');
|
|
return true;
|
|
}
|
|
|
|
function removeTemporaryRemote(worktreePath: string): void {
|
|
try {
|
|
execFileSync('git', ['remote', 'remove', TEMP_REMOTE_NAME], {
|
|
cwd: worktreePath,
|
|
encoding: 'utf-8',
|
|
stdio: 'pipe',
|
|
});
|
|
log.info('Removed temporary origin remote', { worktreePath });
|
|
} catch (err) {
|
|
logError(`Failed to remove temporary remote: ${getErrorMessage(err)}`);
|
|
log.error('git remote remove failed', { worktreePath, error: getErrorMessage(err) });
|
|
}
|
|
}
|