avil13-co 2.2.4 → 2.3.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.
- package/README.md +41 -21
- package/dist/ask.d.ts +4 -3
- package/dist/ask.js +54 -32
- package/dist/cli-commands/index.d.ts +5 -1
- package/dist/cli-commands/index.js +37 -37
- package/dist/commands/checkout-branch.js +5 -9
- package/dist/commands/delete-barnch.d.ts +1 -0
- package/dist/commands/delete-barnch.js +34 -23
- package/dist/commands/exec.d.ts +1 -1
- package/dist/commands/exec.js +11 -2
- package/dist/commands/get-branches.d.ts +2 -4
- package/dist/commands/get-branches.js +18 -35
- package/dist/commands/get-current-branch-name.d.ts +1 -1
- package/dist/commands/get-current-branch-name.js +1 -3
- package/dist/commands/merge-branch.js +27 -31
- package/dist/index.d.ts +1 -1
- package/dist/index.js +35 -19
- package/dist/prompt.d.ts +2 -0
- package/dist/prompt.js +24 -0
- package/dist/terminal.d.ts +5 -0
- package/dist/terminal.js +40 -0
- package/package.json +2 -2
- package/src/__tests__/ask.spec.ts +17 -2
- package/src/__tests__/cli-commands.spec.ts +25 -0
- package/src/__tests__/commands.spec.ts +110 -0
- package/src/__tests__/terminal.spec.ts +56 -0
- package/src/ask.ts +51 -47
- package/src/cli-commands/index.ts +30 -46
- package/src/commands/checkout-branch.ts +4 -12
- package/src/commands/delete-barnch.ts +30 -23
- package/src/commands/exec.ts +11 -7
- package/src/commands/get-branches.ts +15 -41
- package/src/commands/get-current-branch-name.ts +2 -6
- package/src/commands/merge-branch.ts +25 -34
- package/src/index.ts +35 -30
- package/src/prompt.ts +18 -0
- package/src/terminal.ts +32 -0
package/README.md
CHANGED
|
@@ -1,40 +1,60 @@
|
|
|
1
1
|
# avil13/co
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Interactive Git branch checkout, merge and deletion.
|
|
4
4
|
|
|
5
5
|

|
|
6
6
|
|
|
7
|
-
Install
|
|
7
|
+
## Install
|
|
8
8
|
|
|
9
9
|
```sh
|
|
10
10
|
npm install -g avil13-co
|
|
11
11
|
```
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
# Usage
|
|
13
|
+
## Usage
|
|
16
14
|
|
|
17
15
|
```sh
|
|
18
|
-
#
|
|
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 -h # Show help
|
|
20
23
|
```
|
|
21
24
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
```
|
|
25
|
+
Search is case-insensitive and supports subsequences; special characters are literal.
|
|
26
|
+
Filters also work with commands, for example `co -M - 1234` or `co -D - 1234`.
|
|
27
|
+
For deletion, the initial filter restricts the checkbox list.
|
|
26
28
|
|
|
27
|
-
|
|
28
|
-
# Showing merged branches
|
|
29
|
-
co m
|
|
30
|
-
```
|
|
29
|
+
### Delete branches
|
|
31
30
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
31
|
+
Use **Space** to select branches, then **Enter** to confirm the selection.
|
|
32
|
+
A separate confirmation defaults to **No**. Only local branches are listed;
|
|
33
|
+
the current branch is excluded. Like Git's `-D`, this explicitly requested
|
|
34
|
+
operation can delete unmerged branches. Failures are reported per branch,
|
|
35
|
+
without skipping the remaining selections.
|
|
36
|
+
|
|
37
|
+
### Merge
|
|
38
|
+
|
|
39
|
+
After a successful, confirmed merge, `co` offers to delete the source branch
|
|
40
|
+
with **Yes** as the default (`[Y/n]`). This uses safe deletion (`git branch -d`),
|
|
41
|
+
not forced deletion. Remote-only branches are not offered for deletion.
|
|
42
|
+
A failed merge never triggers the deletion question.
|
|
43
|
+
|
|
44
|
+
### Cancel and errors
|
|
45
|
+
|
|
46
|
+
**Ctrl+C** exits with code 130 and restores the previous terminal screen,
|
|
47
|
+
removing this session's interactive output. Completed Git operations are not
|
|
48
|
+
rolled back. On normal completion, command results remain visible.
|
|
49
|
+
Screen switching is only enabled in an interactive terminal.
|
|
50
|
+
|
|
51
|
+
Git errors are printed without an unhandled rejection and return exit code 1.
|
|
52
|
+
Git is invoked directly, without shell interpolation of branch names.
|
|
53
|
+
|
|
54
|
+
## Development
|
|
36
55
|
|
|
37
56
|
```sh
|
|
38
|
-
|
|
39
|
-
|
|
57
|
+
npm test
|
|
58
|
+
npm run type-check
|
|
59
|
+
npm run build
|
|
40
60
|
```
|
package/dist/ask.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
export declare const ask: (message: string, choices: string[]) => Promise<{
|
|
2
|
-
branch:
|
|
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):
|
|
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
|
-
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
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
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
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
|
-
|
|
34
|
-
|
|
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
|
-
|
|
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
|
-
}
|
|
@@ -6,5 +6,9 @@ export declare enum Commands {
|
|
|
6
6
|
ShowMerged = 8,
|
|
7
7
|
ShowUnMerged = 16
|
|
8
8
|
}
|
|
9
|
-
export declare const getWishOfUser: (firstArg?: string
|
|
9
|
+
export declare const getWishOfUser: (firstArg?: string) => Commands;
|
|
10
|
+
export declare function parseArgs(args?: string[]): {
|
|
11
|
+
command: Commands;
|
|
12
|
+
filter: string;
|
|
13
|
+
};
|
|
10
14
|
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";
|
|
@@ -11,45 +10,46 @@ var Commands;
|
|
|
11
10
|
Commands[Commands["ShowMerged"] = 8] = "ShowMerged";
|
|
12
11
|
Commands[Commands["ShowUnMerged"] = 16] = "ShowUnMerged";
|
|
13
12
|
})(Commands = exports.Commands || (exports.Commands = {}));
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
case ['-un', '--no-merged'].includes(arg):
|
|
27
|
-
return Commands.ShowUnMerged;
|
|
28
|
-
default:
|
|
29
|
-
return Commands.Unknown;
|
|
30
|
-
}
|
|
13
|
+
const getWishOfUser = (firstArg = process.argv[2]) => {
|
|
14
|
+
if (['help', '-h', '--h', '--help'].includes(firstArg))
|
|
15
|
+
return Commands.Help;
|
|
16
|
+
if (['-M', 'merge'].includes(firstArg))
|
|
17
|
+
return Commands.MergeBranch;
|
|
18
|
+
if (['-D', 'rm'].includes(firstArg))
|
|
19
|
+
return Commands.DeleteBranch;
|
|
20
|
+
if (['m', '-sm', '--show-merged'].includes(firstArg))
|
|
21
|
+
return Commands.ShowMerged;
|
|
22
|
+
if (['un', '-un', '--no-merged'].includes(firstArg))
|
|
23
|
+
return Commands.ShowUnMerged;
|
|
24
|
+
return Commands.Unknown;
|
|
31
25
|
};
|
|
32
26
|
exports.getWishOfUser = getWishOfUser;
|
|
33
|
-
|
|
34
|
-
|
|
27
|
+
function parseArgs(args = process.argv.slice(2)) {
|
|
28
|
+
const command = (0, exports.getWishOfUser)(args[0] || '');
|
|
29
|
+
if (!args.length)
|
|
30
|
+
return { command, filter: '' };
|
|
31
|
+
if (command === Commands.Unknown && args[0] !== '-') {
|
|
32
|
+
throw new Error('Unknown option: ' + args[0] + '. Use co --help.');
|
|
33
|
+
}
|
|
34
|
+
const rest = args.slice(1);
|
|
35
|
+
if (rest[0] === '-')
|
|
36
|
+
rest.shift();
|
|
37
|
+
return { command, filter: rest.join(' ') };
|
|
38
|
+
}
|
|
39
|
+
exports.parseArgs = parseArgs;
|
|
40
|
+
const getHelp = () => `
|
|
35
41
|
DESCRIPTION:
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
OPTIONS:
|
|
39
|
-
help, -h, --h, --help
|
|
40
|
-
Showing this message
|
|
42
|
+
Quickly switch, merge and delete Git branches.
|
|
41
43
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
+
USAGE:
|
|
45
|
+
co Select a branch to check out
|
|
46
|
+
co - 1234 Start with an editable search filter
|
|
47
|
+
co -M [- filter] Merge, then offer to delete the source branch [Y/n]
|
|
48
|
+
co -D [- filter] Delete multiple local branches (Space to select)
|
|
49
|
+
co m, -sm, --show-merged Show merged branches
|
|
50
|
+
co un, -un, --no-merged Show unmerged branches
|
|
51
|
+
co help, -h, --h, --help Show this message
|
|
44
52
|
|
|
45
|
-
|
|
46
|
-
Showing merged branches
|
|
47
|
-
|
|
48
|
-
-un, --no-merged
|
|
49
|
-
Showing not merged branches
|
|
50
|
-
|
|
51
|
-
-D, rm
|
|
52
|
-
Delete the selected branch
|
|
53
|
+
Ctrl+C cancels and restores the previous terminal screen.
|
|
53
54
|
`;
|
|
54
|
-
};
|
|
55
55
|
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
|
|
6
|
-
//
|
|
5
|
+
const terminal_1 = require("../terminal");
|
|
7
6
|
async function checkoutBranch(branchName) {
|
|
8
|
-
if (!branchName)
|
|
9
|
-
throw new Error('No branch
|
|
10
|
-
|
|
11
|
-
|
|
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,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
|
|
3
|
+
exports.deleteBranch = exports.deleteBranches = void 0;
|
|
4
|
+
const prompt_1 = require("../prompt");
|
|
8
5
|
const exec_1 = require("./exec");
|
|
9
|
-
const
|
|
10
|
-
async function
|
|
11
|
-
|
|
12
|
-
|
|
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
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
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
|
-
|
|
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;
|
package/dist/commands/exec.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare function exec(
|
|
1
|
+
export declare function exec(args: string[]): Promise<string>;
|
package/dist/commands/exec.js
CHANGED
|
@@ -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(
|
|
6
|
-
return new Promise((resolve, reject) =>
|
|
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
|
-
|
|
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
|
-
|
|
12
|
-
|
|
13
|
-
[
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
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<
|
|
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
|
-
|
|
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
|
|
9
|
-
const
|
|
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
|
-
|
|
16
|
-
|
|
17
|
-
|
|
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 (
|
|
36
|
-
|
|
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
|
-
|
|
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;
|
package/dist/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export
|
|
1
|
+
export declare const run: () => Promise<void>;
|