avil13-co 2.2.5 → 2.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/README.md +62 -21
  2. package/dist/ask.d.ts +4 -3
  3. package/dist/ask.js +54 -32
  4. package/dist/cli-commands/index.d.ts +7 -2
  5. package/dist/cli-commands/index.js +44 -37
  6. package/dist/commands/checkout-branch.js +5 -9
  7. package/dist/commands/delete-barnch.d.ts +1 -0
  8. package/dist/commands/delete-barnch.js +34 -23
  9. package/dist/commands/exec.d.ts +1 -1
  10. package/dist/commands/exec.js +11 -2
  11. package/dist/commands/get-branches.d.ts +2 -4
  12. package/dist/commands/get-branches.js +18 -35
  13. package/dist/commands/get-current-branch-name.d.ts +1 -1
  14. package/dist/commands/get-current-branch-name.js +1 -3
  15. package/dist/commands/merge-branch.js +27 -31
  16. package/dist/commands/sync-branches.d.ts +2 -0
  17. package/dist/commands/sync-branches.js +106 -0
  18. package/dist/index.d.ts +1 -1
  19. package/dist/index.js +40 -18
  20. package/dist/prompt.d.ts +2 -0
  21. package/dist/prompt.js +24 -0
  22. package/dist/terminal.d.ts +5 -0
  23. package/dist/terminal.js +40 -0
  24. package/package.json +1 -1
  25. package/src/__tests__/ask.spec.ts +17 -2
  26. package/src/__tests__/cli-commands.spec.ts +31 -0
  27. package/src/__tests__/commands.spec.ts +110 -0
  28. package/src/__tests__/sync-branches.spec.ts +223 -0
  29. package/src/__tests__/terminal.spec.ts +56 -0
  30. package/src/ask.ts +51 -47
  31. package/src/cli-commands/index.ts +36 -46
  32. package/src/commands/checkout-branch.ts +4 -12
  33. package/src/commands/delete-barnch.ts +30 -23
  34. package/src/commands/exec.ts +11 -7
  35. package/src/commands/get-branches.ts +15 -41
  36. package/src/commands/get-current-branch-name.ts +2 -6
  37. package/src/commands/merge-branch.ts +25 -34
  38. package/src/commands/sync-branches.ts +94 -0
  39. package/src/index.ts +40 -28
  40. package/src/prompt.ts +18 -0
  41. package/src/terminal.ts +32 -0
package/README.md CHANGED
@@ -1,40 +1,81 @@
1
1
  # avil13/co
2
2
 
3
- ## Simplest way for use "git checkout"
3
+ Interactive Git branch checkout, merge, deletion and synchronization.
4
4
 
5
5
  ![demo](assets/cli-demo.gif)
6
6
 
7
- Install:
7
+ ## Install
8
8
 
9
9
  ```sh
10
10
  npm install -g avil13-co
11
11
  ```
12
12
 
13
- Type alias "`co`" for switch branch.
14
-
15
- # Usage
13
+ ## Usage
16
14
 
17
15
  ```sh
18
- # Shows a list of branches that can be switched to
19
- co
16
+ co # Search for a branch and check it out
17
+ co - 1234 # Pre-fill the editable search input with "1234"
18
+ co m # Show merged branches (also: -sm, --show-merged)
19
+ co un # Show unmerged branches (also: -un, --no-merged)
20
+ co -M # Merge a selected branch (also: merge)
21
+ co -D # Delete multiple local branches (also: rm)
22
+ co -p # Fetch and safely sync all local branches (like hub sync)
23
+ co -h # Show help
20
24
  ```
21
25
 
22
- ```sh
23
- # Shows help message
24
- co -h
25
- ```
26
+ Search is case-insensitive and supports subsequences; special characters are literal.
27
+ Filters also work with commands, for example `co -M - 1234` or `co -D - 1234`.
28
+ For deletion, the initial filter restricts the checkbox list.
26
29
 
27
- ```sh
28
- # Showing merged branches
29
- co m
30
- ```
30
+ ### Delete branches
31
31
 
32
- ```sh
33
- # Showing not merged branches
34
- co un
35
- ```
32
+ Use **Space** to select branches, then **Enter** to confirm the selection.
33
+ A separate confirmation defaults to **No**. Only local branches are listed;
34
+ the current branch is excluded. Like Git's `-D`, this explicitly requested
35
+ operation can delete unmerged branches. Failures are reported per branch,
36
+ without skipping the remaining selections.
37
+
38
+ ### Merge
39
+
40
+ After a successful, confirmed merge, `co` offers to delete the source branch
41
+ with **Yes** as the default (`[Y/n]`). This uses safe deletion (`git branch -d`),
42
+ not forced deletion. Remote-only branches are not offered for deletion.
43
+ A failed merge never triggers the deletion question.
44
+
45
+ ### Synchronize branches
46
+
47
+ `co -p` works like `hub sync`, without requiring `hub`:
48
+
49
+ - Fetches all remotes with `--prune`.
50
+ - Fast-forwards local branches to their configured upstreams, including branches
51
+ that are not currently checked out. It does not create merge commits or rebase.
52
+ - Without an upstream, uses the same-named branch on `origin`, or a unique match
53
+ on another remote. Ambiguous matches are skipped; tracking configuration is not changed.
54
+ - Warns about unpushed commits or diverged history and leaves those branches unchanged.
55
+ - Safely deletes branches whose remote upstream disappeared only when they are
56
+ merged into the current `HEAD`. Unmerged and checked-out branches are kept.
57
+ - Skips updating the current branch if the working tree is dirty, and never updates
58
+ branches checked out in other worktrees.
59
+
60
+ This command synchronizes **all** local branches without a selection prompt and
61
+ accepts no search filter. It never pushes, force-resets, or stashes changes.
62
+ Network and Git failures are reported with exit code 1; skipped branches are
63
+ reported without treating them as failures.
64
+
65
+ ### Cancel and errors
66
+
67
+ **Ctrl+C** exits with code 130 and restores the previous terminal screen,
68
+ removing this session's interactive output. Completed Git operations are not
69
+ rolled back. On normal completion, command results remain visible.
70
+ Screen switching is only enabled in an interactive terminal.
71
+
72
+ Git errors are printed without an unhandled rejection and return exit code 1.
73
+ Git is invoked directly, without shell interpolation of branch names.
74
+
75
+ ## Development
36
76
 
37
77
  ```sh
38
- # Choosing a branch to delete
39
- co -D
78
+ npm test
79
+ npm run type-check
80
+ npm run build
40
81
  ```
package/dist/ask.d.ts CHANGED
@@ -1,5 +1,6 @@
1
- export declare const ask: (message: string, choices: string[]) => Promise<{
2
- branch: any;
1
+ export declare const ask: (message: string, choices: string[], initialFilter?: string) => Promise<{
2
+ branch: string;
3
3
  }>;
4
+ export declare function askBranches(message: string, choices: string[], filter?: string): Promise<string[]>;
4
5
  export declare function checkItem(item: string, filterString: string): boolean;
5
- export declare function sortOrder(searchString: string, name1: string, name2: string): -1 | 1;
6
+ export declare function sortOrder(searchString: string, name1: string, name2: string): number;
package/dist/ask.js CHANGED
@@ -3,50 +3,72 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.sortOrder = exports.checkItem = exports.ask = void 0;
6
+ exports.sortOrder = exports.checkItem = exports.askBranches = exports.ask = void 0;
7
7
  const inquirer_1 = __importDefault(require("inquirer"));
8
- inquirer_1.default.registerPrompt('autocomplete', require('inquirer-autocomplete-prompt'));
9
- const specSymbols = {
10
- _saveCursor: '\x1b7',
11
- _restoreCursor: '\x1b8',
12
- _clear: '\x1b[H\x1b[2J',
13
- };
14
- const ask = async (message, choices) => {
15
- const prompt = inquirer_1.default.prompt({
16
- //@ts-ignore
8
+ const prompt_1 = require("./prompt");
9
+ const AutocompletePrompt = require('inquirer-autocomplete-prompt');
10
+ class FilteredAutocompletePrompt extends AutocompletePrompt {
11
+ _run(callback) {
12
+ // `default` in the plugin selects a choice, it does not fill the input.
13
+ const filter = this.opt.initialFilter || '';
14
+ this.rl.line = filter;
15
+ this.rl.cursor = filter.length;
16
+ return super._run(callback);
17
+ }
18
+ }
19
+ inquirer_1.default.registerPrompt('autocomplete', FilteredAutocompletePrompt);
20
+ const ask = async (message, choices, initialFilter = '') => {
21
+ return (0, prompt_1.prompt)({
17
22
  type: 'autocomplete',
18
23
  name: 'branch',
19
24
  message,
20
- source(answersSoFar, input = '') {
21
- let list = choices.filter(choiceItem => checkItem(choiceItem, input));
22
- list = list.sort((a, b) => {
23
- return sortOrder(input, a, b);
24
- });
25
- return Promise.resolve(list);
26
- }
25
+ initialFilter,
26
+ source(_answers, input = initialFilter) {
27
+ return Promise.resolve(choices
28
+ .filter(choice => checkItem(choice, input))
29
+ .sort((a, b) => sortOrder(input, a, b)));
30
+ },
27
31
  });
28
- return prompt;
29
32
  };
30
33
  exports.ask = ask;
31
- //
34
+ async function askBranches(message, choices, filter = '') {
35
+ const filtered = choices.filter(choice => checkItem(choice, filter));
36
+ if (!filtered.length)
37
+ throw new Error('No branches match the filter.');
38
+ const { branches } = await (0, prompt_1.prompt)({
39
+ type: 'checkbox',
40
+ name: 'branches',
41
+ message,
42
+ choices: filtered,
43
+ validate: (selected) => selected.length > 0 || 'Select at least one branch.',
44
+ });
45
+ return branches;
46
+ }
47
+ exports.askBranches = askBranches;
32
48
  function checkItem(item, filterString) {
33
- const reg = getRegExp(filterString);
34
- return reg.test(item);
49
+ // Literal, case-insensitive subsequence matching; no user-supplied regex.
50
+ const needle = filterString.replace(/\s/g, '').toLowerCase();
51
+ const haystack = item.toLowerCase();
52
+ let position = 0;
53
+ for (const character of needle) {
54
+ position = haystack.indexOf(character, position);
55
+ if (position === -1)
56
+ return false;
57
+ position++;
58
+ }
59
+ return true;
35
60
  }
36
61
  exports.checkItem = checkItem;
37
62
  function sortOrder(searchString, name1, name2) {
38
- if (!name1.includes(searchString)) {
63
+ const search = searchString.toLowerCase();
64
+ const first = name1.toLowerCase().indexOf(search);
65
+ const second = name2.toLowerCase().indexOf(search);
66
+ if (first === second)
67
+ return 0;
68
+ if (first === -1)
39
69
  return 1;
40
- }
41
- if (!name2.includes(searchString)) {
70
+ if (second === -1)
42
71
  return -1;
43
- }
44
- if ((name2.indexOf(searchString) < name1.indexOf(searchString))) {
45
- return 1;
46
- }
47
- return -1;
72
+ return first - second;
48
73
  }
49
74
  exports.sortOrder = sortOrder;
50
- function getRegExp(filterString) {
51
- return new RegExp(filterString.split('').map(s => s.trim()).filter(Boolean).join('.*').replace('.*.*', '.*'), 'gi');
52
- }
@@ -4,7 +4,12 @@ export declare enum Commands {
4
4
  DeleteBranch = 2,
5
5
  MergeBranch = 4,
6
6
  ShowMerged = 8,
7
- ShowUnMerged = 16
7
+ ShowUnMerged = 16,
8
+ Sync = 32
8
9
  }
9
- export declare const getWishOfUser: (firstArg?: string | undefined) => Commands;
10
+ export declare const getWishOfUser: (firstArg?: string) => Commands;
11
+ export declare function parseArgs(args?: string[]): {
12
+ command: Commands;
13
+ filter: string;
14
+ };
10
15
  export declare const getHelp: () => string;
@@ -1,7 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getHelp = exports.getWishOfUser = exports.Commands = void 0;
4
- const args = process.argv.slice(2);
3
+ exports.getHelp = exports.parseArgs = exports.getWishOfUser = exports.Commands = void 0;
5
4
  var Commands;
6
5
  (function (Commands) {
7
6
  Commands[Commands["Unknown"] = 0] = "Unknown";
@@ -10,46 +9,54 @@ var Commands;
10
9
  Commands[Commands["MergeBranch"] = 4] = "MergeBranch";
11
10
  Commands[Commands["ShowMerged"] = 8] = "ShowMerged";
12
11
  Commands[Commands["ShowUnMerged"] = 16] = "ShowUnMerged";
12
+ Commands[Commands["Sync"] = 32] = "Sync";
13
13
  })(Commands = exports.Commands || (exports.Commands = {}));
14
- ;
15
- const getWishOfUser = (firstArg) => {
16
- const arg = firstArg || args[0];
17
- switch (true) {
18
- case ['help', '-h', '--h', '--help'].includes(arg):
19
- return Commands.Help;
20
- case ['-M', 'merge'].includes(arg):
21
- return Commands.MergeBranch;
22
- case ['-D', 'rm'].includes(arg):
23
- return Commands.DeleteBranch;
24
- case ['-sm', '--show-merged'].includes(arg):
25
- return Commands.ShowMerged;
26
- case ['-un', '--no-merged'].includes(arg):
27
- return Commands.ShowUnMerged;
28
- default:
29
- return Commands.Unknown;
30
- }
14
+ const getWishOfUser = (firstArg = process.argv[2]) => {
15
+ if (['help', '-h', '--h', '--help'].includes(firstArg))
16
+ return Commands.Help;
17
+ if (['-M', 'merge'].includes(firstArg))
18
+ return Commands.MergeBranch;
19
+ if (['-D', 'rm'].includes(firstArg))
20
+ return Commands.DeleteBranch;
21
+ if (firstArg === '-p')
22
+ return Commands.Sync;
23
+ if (['m', '-sm', '--show-merged'].includes(firstArg))
24
+ return Commands.ShowMerged;
25
+ if (['un', '-un', '--no-merged'].includes(firstArg))
26
+ return Commands.ShowUnMerged;
27
+ return Commands.Unknown;
31
28
  };
32
29
  exports.getWishOfUser = getWishOfUser;
33
- const getHelp = () => {
34
- return `
30
+ function parseArgs(args = process.argv.slice(2)) {
31
+ const command = (0, exports.getWishOfUser)(args[0] || '');
32
+ if (!args.length)
33
+ return { command, filter: '' };
34
+ if (command === Commands.Unknown && args[0] !== '-') {
35
+ throw new Error('Unknown option: ' + args[0] + '. Use co --help.');
36
+ }
37
+ if (command === Commands.Sync && args.length > 1) {
38
+ throw new Error('co -p synchronizes all branches and does not accept a filter.');
39
+ }
40
+ const rest = args.slice(1);
41
+ if (rest[0] === '-')
42
+ rest.shift();
43
+ return { command, filter: rest.join(' ') };
44
+ }
45
+ exports.parseArgs = parseArgs;
46
+ const getHelp = () => `
35
47
  DESCRIPTION:
36
- A console program for quickly switching between branches
37
-
38
- OPTIONS:
39
- help, -h, --h, --help
40
- Showing this message
48
+ Quickly switch, merge, delete and synchronize Git branches.
41
49
 
42
- -M, merge
43
- Merge branch
50
+ USAGE:
51
+ co Select a branch to check out
52
+ co - 1234 Start with an editable search filter
53
+ co -M [- filter] Merge, then offer to delete the source branch [Y/n]
54
+ co -D [- filter] Delete multiple local branches (Space to select)
55
+ co -p Fetch and safely sync all local branches (like hub sync)
56
+ co m, -sm, --show-merged Show merged branches
57
+ co un, -un, --no-merged Show unmerged branches
58
+ co help, -h, --h, --help Show this message
44
59
 
45
- -sm, --show-merged
46
- Showing merged branches
47
-
48
- -un, --no-merged
49
- Showing not merged branches
50
-
51
- -D, rm
52
- Delete the selected branch
60
+ Ctrl+C cancels and restores the previous terminal screen.
53
61
  `;
54
- };
55
62
  exports.getHelp = getHelp;
@@ -2,15 +2,11 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.checkoutBranch = void 0;
4
4
  const exec_1 = require("./exec");
5
- const color_1 = require("../color");
6
- //
5
+ const terminal_1 = require("../terminal");
7
6
  async function checkoutBranch(branchName) {
8
- if (!branchName) {
9
- throw new Error('No branch...');
10
- }
11
- const checkoutCommand = `git checkout ${branchName}`;
12
- console.log(' ' + color_1.clc.green('git checkout', branchName) + '\n');
13
- const checkoutCommandResult = await (0, exec_1.exec)(checkoutCommand);
14
- console.log(checkoutCommandResult);
7
+ if (!branchName)
8
+ throw new Error('No branch selected.');
9
+ (0, terminal_1.print)('git checkout ' + branchName);
10
+ (0, terminal_1.print)(await (0, exec_1.exec)(['checkout', branchName, '--']));
15
11
  }
16
12
  exports.checkoutBranch = checkoutBranch;
@@ -1 +1,2 @@
1
+ export declare function deleteBranches(branchNames: string[], confirm?: boolean, force?: boolean): Promise<void>;
1
2
  export declare function deleteBranch(branchName: string): Promise<void>;
@@ -1,30 +1,41 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
2
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.deleteBranch = void 0;
7
- const inquirer_1 = __importDefault(require("inquirer"));
3
+ exports.deleteBranch = exports.deleteBranches = void 0;
4
+ const prompt_1 = require("../prompt");
8
5
  const exec_1 = require("./exec");
9
- const color_1 = require("../color");
10
- async function deleteBranch(branchName) {
11
- if (!branchName) {
12
- throw new Error('No branch...');
6
+ const terminal_1 = require("../terminal");
7
+ async function deleteBranches(branchNames, confirm = true, force = true) {
8
+ const branches = [...new Set(branchNames)];
9
+ if (!branches.length || branches.some(branch => !branch)) {
10
+ throw new Error('No branches selected.');
11
+ }
12
+ if (confirm) {
13
+ const { answer } = await (0, prompt_1.prompt)({
14
+ type: 'confirm',
15
+ name: 'answer',
16
+ message: 'Delete these branches: ' + branches.join(', ') + '?',
17
+ default: false,
18
+ });
19
+ if (!answer) {
20
+ (0, terminal_1.print)('Branches were not deleted.');
21
+ return;
22
+ }
13
23
  }
14
- const res = await inquirer_1.default.prompt({
15
- type: 'confirm',
16
- name: 'answer',
17
- message: color_1.clc.yellow('Are you sure you want to delete the branch "') + color_1.clc.red(branchName) + color_1.clc.yellow('"?'),
18
- default: false,
19
- });
20
- if (res.answer === true) {
21
- const command = `git branch -D ${branchName}`;
22
- console.log(' ' + color_1.clc.redBg(`git branch -D ${branchName}`, '') + '\n');
23
- const checkoutCommandResult = await (0, exec_1.exec)(command);
24
- console.log(checkoutCommandResult);
25
- console.log(color_1.clc.yellow('Branch'), color_1.clc.red(branchName), color_1.clc.yellow('has been deleted'));
26
- return;
24
+ // Attempt every selected branch and report partial failures as well.
25
+ const errors = [];
26
+ for (const branch of branches) {
27
+ try {
28
+ (0, terminal_1.print)(await (0, exec_1.exec)(['branch', force ? '-D' : '-d', '--', branch]));
29
+ }
30
+ catch (error) {
31
+ errors.push(branch + ': ' + (error instanceof Error ? error.message : String(error)));
32
+ }
27
33
  }
28
- console.log(color_1.clc.yellow('The branch was not deleted'));
34
+ if (errors.length)
35
+ throw new Error(errors.join('\n'));
36
+ }
37
+ exports.deleteBranches = deleteBranches;
38
+ async function deleteBranch(branchName) {
39
+ return deleteBranches([branchName]);
29
40
  }
30
41
  exports.deleteBranch = deleteBranch;
@@ -1 +1 @@
1
- export declare function exec(command: any): Promise<string>;
1
+ export declare function exec(args: string[]): Promise<string>;
@@ -2,7 +2,16 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.exec = void 0;
4
4
  const child_process_1 = require("child_process");
5
- function exec(command) {
6
- return new Promise((resolve, reject) => (0, child_process_1.exec)(command, (err, stdout) => err ? reject(err) : resolve(stdout)));
5
+ function exec(args) {
6
+ return new Promise((resolve, reject) => {
7
+ (0, child_process_1.execFile)('git', args, (error, stdout, stderr) => {
8
+ if (error) {
9
+ reject(new Error([stderr.trim(), stdout.trim()].filter(Boolean).join('\n') || error.message));
10
+ }
11
+ else {
12
+ resolve([stdout.trimEnd(), stderr.trimEnd()].filter(Boolean).join('\n'));
13
+ }
14
+ });
15
+ });
7
16
  }
8
17
  exports.exec = exec;
@@ -3,7 +3,5 @@ export declare enum BranchesType {
3
3
  Merged = 1,
4
4
  NotMerged = 2
5
5
  }
6
- /**
7
- * get branch list
8
- */
9
- export declare function getBranches(type: BranchesType): Promise<string[]>;
6
+ /** Remote origin refs are also offered for checkout/merge; deletion is local only. */
7
+ export declare function getBranches(type: BranchesType, localOnly?: boolean): Promise<string[]>;
@@ -8,40 +8,23 @@ var BranchesType;
8
8
  BranchesType[BranchesType["Merged"] = 1] = "Merged";
9
9
  BranchesType[BranchesType["NotMerged"] = 2] = "NotMerged";
10
10
  })(BranchesType = exports.BranchesType || (exports.BranchesType = {}));
11
- const commandsForGetBranches = {
12
- [BranchesType.All]: 'git branch --all',
13
- [BranchesType.Merged]: 'git branch --all --merged',
14
- [BranchesType.NotMerged]: 'git branch --all --no-merged',
15
- };
16
- /**
17
- * get branch list
18
- */
19
- function getBranches(type) {
20
- const command = commandsForGetBranches[type];
21
- return (0, exec_1.exec)(command)
22
- .then(parseBranches)
23
- .then(branches => {
24
- if (branches.length) {
25
- return branches;
26
- }
27
- throw new Error('No branches found...');
28
- });
11
+ /** Remote origin refs are also offered for checkout/merge; deletion is local only. */
12
+ async function getBranches(type, localOnly = false) {
13
+ const args = ['branch', '--format=%(refname)'];
14
+ if (!localOnly)
15
+ args.push('--all');
16
+ if (type === BranchesType.Merged)
17
+ args.push('--merged');
18
+ if (type === BranchesType.NotMerged)
19
+ args.push('--no-merged');
20
+ const stdout = await (0, exec_1.exec)(args);
21
+ const branches = [...new Set(stdout.split('\n')
22
+ .map(name => name.trim())
23
+ .filter(name => name && !/^refs\/remotes\/.+\/HEAD$/.test(name))
24
+ .map(name => name.replace(/^refs\/heads\//, '')
25
+ .replace(/^refs\/remotes\/(?:origin\/)?/, '')))];
26
+ if (!branches.length)
27
+ throw new Error('No branches found.');
28
+ return branches;
29
29
  }
30
30
  exports.getBranches = getBranches;
31
- function parseBranches(stdout) {
32
- return stdout
33
- .split('\n')
34
- .filter(s => !/\s->\s/.test(s))
35
- .map(cleanBranchName)
36
- .filter(Boolean)
37
- .filter(onlyUnique);
38
- }
39
- function cleanBranchName(name) {
40
- return name
41
- .replace(/^\*/, '')
42
- .replace(/remotes\/origin\//, '')
43
- .trim();
44
- }
45
- function onlyUnique(value, index, self) {
46
- return self.indexOf(value) === index;
47
- }
@@ -1 +1 @@
1
- export declare function getCurrentBranchName(): Promise<void>;
1
+ export declare function getCurrentBranchName(): Promise<string>;
@@ -3,8 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getCurrentBranchName = void 0;
4
4
  const exec_1 = require("./exec");
5
5
  async function getCurrentBranchName() {
6
- const currentBranchName = `git rev-parse --abbrev-ref HEAD`;
7
- const stdout = await (0, exec_1.exec)(currentBranchName);
8
- console.log(stdout);
6
+ return (await (0, exec_1.exec)(['rev-parse', '--abbrev-ref', 'HEAD'])).trim();
9
7
  }
10
8
  exports.getCurrentBranchName = getCurrentBranchName;
@@ -1,44 +1,40 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
2
  Object.defineProperty(exports, "__esModule", { value: true });
6
3
  exports.mergeBranch = void 0;
7
4
  const exec_1 = require("./exec");
8
- const color_1 = require("../color");
9
- const inquirer_1 = __importDefault(require("inquirer"));
10
- //
5
+ const get_current_branch_name_1 = require("./get-current-branch-name");
6
+ const delete_barnch_1 = require("./delete-barnch");
7
+ const terminal_1 = require("../terminal");
8
+ const prompt_1 = require("../prompt");
11
9
  async function mergeBranch(branchName) {
12
- if (!branchName) {
13
- throw new Error('No branch...');
14
- }
15
- const currentBranch = await (0, exec_1.exec)('git rev-parse --abbrev-ref HEAD');
16
- const message = [
17
- color_1.clc._blue,
18
- 'Do you want to merge branch ',
19
- color_1.clc._green,
20
- branchName,
21
- color_1.clc._blue,
22
- ' into ',
23
- color_1.clc._green,
24
- currentBranch,
25
- color_1.clc._blue,
26
- '?',
27
- color_1.clc._off,
28
- ].join('');
29
- const res = await inquirer_1.default.prompt({
10
+ if (!branchName)
11
+ throw new Error('No branch selected.');
12
+ const currentBranch = await (0, get_current_branch_name_1.getCurrentBranchName)();
13
+ if (branchName === currentBranch)
14
+ throw new Error('Cannot merge the current branch into itself.');
15
+ const { answer } = await (0, prompt_1.prompt)({
30
16
  type: 'confirm',
31
17
  name: 'answer',
32
- message,
18
+ message: 'Merge branch ' + branchName + ' into ' + currentBranch + '?',
33
19
  default: false,
34
20
  });
35
- if (res.answer === true) {
36
- const checkoutCommand = `git merge ${branchName}`;
37
- console.log(' ' + color_1.clc.green('git merge', branchName) + '\n');
38
- const checkoutCommandResult = await (0, exec_1.exec)(checkoutCommand);
39
- console.log(checkoutCommandResult);
21
+ if (!answer) {
22
+ (0, terminal_1.print)('Branch was not merged.');
40
23
  return;
41
24
  }
42
- console.log(color_1.clc.yellow('The branch was not merged'));
25
+ (0, terminal_1.print)('git merge ' + branchName);
26
+ (0, terminal_1.print)(await (0, exec_1.exec)(['merge', '--', branchName]));
27
+ // Only local branches can be deleted; never remove remote refs.
28
+ const locals = (await (0, exec_1.exec)(['for-each-ref', '--format=%(refname)', 'refs/heads/'])).split('\n');
29
+ if (!locals.includes('refs/heads/' + branchName))
30
+ return;
31
+ const { remove } = await (0, prompt_1.prompt)({
32
+ type: 'confirm',
33
+ name: 'remove',
34
+ message: 'Delete merged branch ' + branchName + '?',
35
+ default: true,
36
+ });
37
+ if (remove)
38
+ await (0, delete_barnch_1.deleteBranches)([branchName], false, false);
43
39
  }
44
40
  exports.mergeBranch = mergeBranch;
@@ -0,0 +1,2 @@
1
+ /** Synchronize local branches without switching branches or rewriting commits. */
2
+ export declare function syncBranches(): Promise<void>;