diff --git a/src/commands/CancelCommand.ts b/src/commands/CancelCommand.ts index 0199bb5..2c167da 100644 --- a/src/commands/CancelCommand.ts +++ b/src/commands/CancelCommand.ts @@ -49,6 +49,9 @@ export class CancelCommand extends CLICommand { args.reason as string ) console.log(`Issue #${issue.id} is now cancelled`) + if (branch !== "develop") { + console.log(`Switch back to develop: git checkout develop`) + } return 0 } } diff --git a/src/commands/CreateCommand.ts b/src/commands/CreateCommand.ts index 8972235..bf84e55 100644 --- a/src/commands/CreateCommand.ts +++ b/src/commands/CreateCommand.ts @@ -78,6 +78,7 @@ export class CreateCommand extends CLICommand { writeTodoFile(todo) commitFile("TODO", `todo(${nextId}): open`) console.log(`Created issue #${nextId}: ${args.title}`) + console.log(`Start working: mime-todo start ${nextId}`) return 0 } } diff --git a/src/commands/DoneCommand.ts b/src/commands/DoneCommand.ts index 13d3ec7..921d496 100644 --- a/src/commands/DoneCommand.ts +++ b/src/commands/DoneCommand.ts @@ -1,7 +1,7 @@ import type { Argv, ArgumentsCamelCase } from "yargs" import { CLICommand } from "../cli/CLICommand.js" import { parseTodoFile, writeTodoFile } from "../file.js" -import { getCurrentBranch, commitFileWithBody } from "../git.js" +import { getCurrentBranch, commitFileWithBody, getDirtySubmodules } from "../git.js" import { validateStatusTransition } from "../issue.js" export class DoneCommand extends CLICommand { @@ -17,6 +17,11 @@ export class DoneCommand extends CLICommand { demandOption: true, description: "High-level summary of what was delivered", }) + .option("confirm", { + type: "boolean", + default: false, + description: "Confirm that submodule branches have been merged and pointer updated", + }) } async execute(args: ArgumentsCamelCase): Promise { @@ -41,6 +46,14 @@ export class DoneCommand extends CLICommand { return 1 } + // Check for dirty submodules + const dirtySubmodules = getDirtySubmodules() + if (dirtySubmodules.length > 0 && !(args.confirm as boolean)) { + console.error(`Submodule(s) have uncommitted changes or modified pointers: ${dirtySubmodules.join(", ")}`) + console.error(`Ensure feature branches are merged and pointers updated, then run with --confirm`) + return 1 + } + issue.status = "done" writeTodoFile(todo) commitFileWithBody( @@ -49,6 +62,8 @@ export class DoneCommand extends CLICommand { args.summary as string ) console.log(`Issue #${issue.id} is now done`) + console.log(`Merge to develop: git checkout develop && git merge ${expectedBranch} --no-ff`) + console.log(`Then push to Bugzilla: mime-todo push`) return 0 } } diff --git a/src/commands/HoldCommand.ts b/src/commands/HoldCommand.ts index 65f9223..8e7e812 100644 --- a/src/commands/HoldCommand.ts +++ b/src/commands/HoldCommand.ts @@ -48,6 +48,7 @@ export class HoldCommand extends CLICommand { args.reason as string ) console.log(`Issue #${issue.id} is now on hold`) + console.log(`Switch back to develop: git checkout develop`) return 0 } } diff --git a/src/commands/InitCommand.ts b/src/commands/InitCommand.ts index df5a17c..842af31 100644 --- a/src/commands/InitCommand.ts +++ b/src/commands/InitCommand.ts @@ -152,6 +152,7 @@ export class InitCommand extends CLICommand { } console.log(`\nInit complete: ${created} items created`) + console.log(`Push issues to Bugzilla: mime-todo push`) return 0 } } diff --git a/src/commands/StartCommand.ts b/src/commands/StartCommand.ts index a5bed0a..c750f61 100644 --- a/src/commands/StartCommand.ts +++ b/src/commands/StartCommand.ts @@ -55,6 +55,7 @@ export class StartCommand extends CLICommand { ) console.log(`Issue #${issue.id} is now in-progress`) console.log(`Create the issue branch: git checkout -b ${issueBranch}`) + console.log(`If working in a submodule, also checkout there: cd && git checkout -b ${issueBranch}`) return 0 } } diff --git a/src/git.ts b/src/git.ts index 83ed707..73a1404 100644 --- a/src/git.ts +++ b/src/git.ts @@ -87,6 +87,19 @@ function parseGitLog(range: string, cwd: string): GitCommit[] { return commits } +// Check for dirty or modified submodules +export function getDirtySubmodules(cwd = process.cwd()): string[] { + try { + const output = execSync("git submodule status", { cwd, encoding: "utf-8" }).trim() + if (!output) return [] + return output.split("\n") + .filter(line => line.startsWith("+") || line.startsWith("-")) + .map(line => line.trim().split(/\s+/)[1]) + } catch { + return [] + } +} + // Check if a commit subject is a todo transition export function parseTodoTransition(subject: string): { issueId: number; status: string } | null { const match = subject.match(/^todo\((\d+)\):\s*([a-z-]+)/)