UNPKG

8.77 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3var Fs = require("fs-extra");
4var Minimist = require("minimist");
5var git_1 = require("./git");
6var local_storage_1 = require("./local-storage");
7var paths_1 = require("./paths");
8var step_1 = require("./step");
9var submodule_1 = require("./submodule");
10var utils_1 = require("./utils");
11/**
12 The rebase module is responsible for performing tasks done by the editor using an
13 interactive rebase.
14 */
15function init() {
16 if (require.main !== module) {
17 return;
18 }
19 var argv = Minimist(process.argv.slice(2), {
20 string: ['_'],
21 });
22 var method = argv._[0];
23 var arg1 = argv._[1];
24 switch (method) {
25 case 'reword':
26 return rewordRecentStep(arg1);
27 case 'super-pick':
28 return superPickStep(arg1);
29 case 'rebranch-super':
30 return rebranchSuperSteps();
31 case 'stash-rebase-state':
32 return stashRebaseState(arg1);
33 }
34}
35init();
36// Responsible for editing the recent commit's message. It will also sort the step's
37// number if needed
38function rewordRecentStep(message) {
39 // Calculate next step based on the current commit's message
40 var commitMessage = git_1.Git.recentCommit(['--format=%s']);
41 var stepDescriptor = step_1.Step.descriptor(commitMessage);
42 var nextStep = getNextStep(stepDescriptor);
43 // Open the editor by default
44 var args = ['commit', '--amend', '--allow-empty'];
45 // If message provided skip editor
46 if (message) {
47 args.push('-m', message);
48 }
49 // Specified step is gonna be used for when forming the commit message
50 local_storage_1.localStorage.setItem('HOOK_STEP', nextStep);
51 // This will be used later on to update the manuals
52 if (stepDescriptor && step_1.Step.ensureStepMap()) {
53 step_1.Step.updateStepMap('reset', { oldStep: stepDescriptor.number, newStep: nextStep });
54 }
55 // commit, let git hooks do the rest
56 git_1.Git.print(args);
57}
58exports.rewordRecentStep = rewordRecentStep;
59// The super-picker is responsible for cherry-picking super steps and
60// rename their manual files
61function superPickStep(hash) {
62 var message = git_1.Git.recentCommit(hash, ['--format=%s']);
63 var oldStep = step_1.Step.descriptor(message).number;
64 var newStep = step_1.Step.nextSuper();
65 // Fetch patch data
66 var diff = newStep - oldStep;
67 var stepFilePattern = /step(\d+)\.(md|tmpl)/g;
68 var patch = git_1.Git(['format-patch', '-1', hash, '--stdout']);
69 // Replace references for old manual files with new manual files
70 var fixedPatch = patch.replace(stepFilePattern, function (file, step, extension) {
71 step = Number(step) + diff;
72 return "step" + step + "." + extension;
73 });
74 var submoduleCwd = local_storage_1.localStorage.getItem('SUBMODULE_CWD');
75 var stepMap = step_1.Step.getStepMap(submoduleCwd, true);
76 if (stepMap) {
77 // The submodule cwd was given from another process of tortilla
78 var submodule_2 = submodule_1.Submodule.getLocalName(submoduleCwd);
79 var diffStepPattern = /\{\{\s*diffStep\s+"?(\d+\.\d+)"?.*\}\}/g;
80 // Replace indexes presented in diffStep() template helpers
81 fixedPatch = fixedPatch.replace(diffStepPattern, function (helper, oldStepId) {
82 var helperSubmodule = helper.match(/module\s?=\s?"?([^\s"]+)"?/);
83 helperSubmodule = helperSubmodule ? helperSubmodule[1] : '';
84 // Don't replace anything if submodules don't match
85 if (helperSubmodule !== submodule_2) {
86 return helper;
87 }
88 // In case step has been removed in the process, replace it with a meaningless placeholder
89 var newStepId = stepMap[oldStepId] || 'XX.XX';
90 return helper.replace(/(diffStep\s+"?)\d+\.\d+/, "$1" + newStepId);
91 });
92 }
93 // Apply patch
94 git_1.Git(['am'], {
95 input: fixedPatch,
96 });
97}
98exports.superPickStep = superPickStep;
99// Updates the branches referencing all super steps
100function rebranchSuperSteps() {
101 var rootBranch = git_1.Git.activeBranchName();
102 // Delete root
103 try {
104 git_1.Git(['branch', '-D', rootBranch + "-root"]);
105 }
106 catch (e) {
107 // Ignore
108 }
109 // Delete steps
110 git_1.Git(['branch']).split('\n').filter(function (branch) {
111 return branch.match(new RegExp(rootBranch + "-step\\d+"));
112 })
113 .forEach(function (branch) {
114 git_1.Git(['branch', '-D', branch.trim()]);
115 });
116 // Branch root
117 git_1.Git(['branch', rootBranch + "-root", git_1.Git.rootHash()]);
118 // Branch steps
119 git_1.Git(['log', '--format=%H %s', '--grep=^Step [0-9]\\+:'])
120 .split('\n')
121 .filter(Boolean)
122 .map(function (log) {
123 var message = log.split(' ');
124 var hash = message.shift();
125 message = message.join(' ');
126 return {
127 number: step_1.Step.descriptor(message).number,
128 hash: hash,
129 };
130 })
131 .forEach(function (step) {
132 git_1.Git(['branch', rootBranch + "-step" + step.number, step.hash]);
133 });
134}
135exports.rebranchSuperSteps = rebranchSuperSteps;
136function getPreviousEditedSteps() {
137 return git_1.Git(['log', '--format=%s'], {
138 cwd: paths_1.Paths.rebaseStates,
139 }).split('\n').slice(1);
140}
141exports.getPreviousEditedSteps = getPreviousEditedSteps;
142// Given a step, it will look for its belonging rebase state and will restore everything
143// to that point of time, including todo and tortilla local storage
144function hardResetRebaseState(step) {
145 // HEAD on rebase state should now reference provided step
146 var rebaseStateObject = git_1.Git(['log', "--grep=" + step, '--format=%H'], {
147 cwd: paths_1.Paths.rebaseStates,
148 });
149 git_1.Git(['reset', '--hard', rebaseStateObject], {
150 cwd: paths_1.Paths.rebaseStates,
151 });
152 var rebaseStatesStorage = new local_storage_1.localStorage.native(paths_1.Paths.rebaseStates);
153 var head = rebaseStatesStorage.getItem('HEAD');
154 // Hard reset HEAD from rebase state
155 git_1.Git(['reset', '--hard', head]);
156 // Restore essential local storage items
157 local_storage_1.localStorage.setItem('REBASE_OLD_STEP', rebaseStatesStorage.getItem('REBASE_OLD_STEP'));
158 local_storage_1.localStorage.setItem('REBASE_NEW_STEP', rebaseStatesStorage.getItem('REBASE_NEW_STEP'));
159 local_storage_1.localStorage.removeItem('REBASE_HOOKS_DISABLED');
160 // Restore todo from rebase state
161 git_1.Git(['rebase', '--edit-todo'], {
162 env: {
163 GIT_SEQUENCE_EDITOR: "node " + paths_1.Paths.tortilla.editor + " reset-todo"
164 }
165 });
166 var statusMessage = git_1.Git(['log', '-1', '--format=%h... %s']);
167 // Match git's native API log
168 console.log(utils_1.freeText("\n Stopped at " + statusMessage + "\n You can amend the commit now, with\n\n git commit --amend\n\n Once you are satisfied with your changes, run\n\n git rebase --continue\n "));
169}
170exports.hardResetRebaseState = hardResetRebaseState;
171// Will create a new rebase state so we can go back to it during the editing process
172function stashRebaseState(todoFile) {
173 var todo = Fs.readFileSync(todoFile).toString();
174 var tasks = todo.split('\n');
175 var _a = tasks[0].trim().match(/edit +(\w+) +Step +(\d+(?:\.\d+)?)/) || [], _b = _a[1], head = _b === void 0 ? '' : _b, _c = _a[2], step = _c === void 0 ? '' : _c;
176 if (!head || !step) {
177 return;
178 }
179 var rebaseStatesStorage = new local_storage_1.localStorage.native(paths_1.Paths.rebaseStates);
180 // Since the execution comes BEFORE the edit itself, we need to slice it out to get
181 // a todo list which is right for the edit state
182 todo = tasks.slice(1).join('\n');
183 // Save essential local storage variables for step editing
184 rebaseStatesStorage.setItem('REBASE_OLD_STEP', local_storage_1.localStorage.getItem('REBASE_OLD_STEP') || step);
185 rebaseStatesStorage.setItem('REBASE_NEW_STEP', local_storage_1.localStorage.getItem('REBASE_NEW_STEP') || step);
186 rebaseStatesStorage.setItem('HEAD', git_1.Git(['rev-parse', head]));
187 rebaseStatesStorage.setItem('TODO', todo);
188 // Edit on top of the rebase_states stack, using git commits
189 git_1.Git(['add', '.'], {
190 cwd: paths_1.Paths.rebaseStates,
191 });
192 git_1.Git(['commit', '-m', step], {
193 cwd: paths_1.Paths.rebaseStates,
194 });
195}
196exports.stashRebaseState = stashRebaseState;
197// Calculate the next step dynamically based on its super flag
198function getNextStep(stepDescriptor) {
199 if (!stepDescriptor) {
200 return '';
201 }
202 var isSubStep = !!stepDescriptor.number.split('.')[1];
203 return isSubStep ? step_1.Step.next(1) : step_1.Step.nextSuper(1);
204}
205//# sourceMappingURL=rebase.js.map
\No newline at end of file