33const path = require ( 'path' ) ;
44
55const {
6- runAsync, runSync, forceRunAsync, exit
6+ runAsync, runSync, forceRunAsync
77} = require ( './run' ) ;
88const Session = require ( './session' ) ;
99
@@ -46,17 +46,10 @@ class LandingSession extends Session {
4646 cli . ok ( `Aborted \`git node land\` session in ${ this . ncuDir } ` ) ;
4747 }
4848
49- async apply ( ) {
49+ async downloadAndPatch ( ) {
5050 const { cli, req, repo, owner, prid } = this ;
5151
52- if ( ! this . readyToApply ( ) ) {
53- cli . warn ( 'This session can not proceed to apply patches, ' +
54- 'run `git node land --abort`' ) ;
55- return ;
56- }
57- await this . tryResetBranch ( ) ;
58-
59- // TODO: restore previously downloaded patches
52+ // TODO(joyeecheung): restore previously downloaded patches
6053 cli . startSpinner ( `Downloading patch for ${ prid } ` ) ;
6154 const patch = await req . text (
6255 `https://github.com/${ owner } /${ repo } /pull/${ prid } .patch` ) ;
@@ -81,13 +74,42 @@ class LandingSession extends Session {
8174 ] ) ;
8275 } else {
8376 cli . error ( 'Failed to apply patches' ) ;
84- exit ( ) ;
77+ process . exit ( 1 ) ;
8578 }
8679 }
8780 cli . ok ( 'Patches applied' ) ;
81+ return patch ;
82+ }
8883
89- this . startAmending ( ) ;
90- if ( / S u b j e c t : \[ P A T C H \] / . test ( patch ) ) {
84+ getRebaseSuggestion ( subjects ) {
85+ const { upstream, branch } = this ;
86+ let command = `git rebase ${ upstream } /${ branch } -i` ;
87+ command += ' -x "git node land --amend"' ;
88+
89+ const squashes = subjects . filter (
90+ line => line . includes ( 'fixup!' ) || line . includes ( 'squash!' ) ) ;
91+
92+ if ( squashes . length !== 0 ) {
93+ command += ' --autosquash' ;
94+ }
95+
96+ return command ;
97+ }
98+
99+ async suggestAfterPatch ( patch ) {
100+ const { cli } = this ;
101+ const subjects = patch . match ( / S u b j e c t : \[ P A T C H .* ?\] .* / g) ;
102+ if ( ! subjects ) {
103+ cli . warn ( 'Cannot get number of commits in the patch. ' +
104+ 'It seems to be malformed' ) ;
105+ return ;
106+ }
107+
108+ // XXX(joyeecheung) we cannot guarantee that no one will put a subject
109+ // line in the commit message but that seems unlikely (some deps update
110+ // might do that).
111+ if ( subjects . length === 1 ) {
112+ // assert(subjects[0].startsWith('Subject: [PATCH]'))
91113 const shouldAmend = await cli . prompt (
92114 'There is only one commit in this PR.\n' +
93115 'do you want to amend the commit message?' ) ;
@@ -101,20 +123,25 @@ class LandingSession extends Session {
101123 return this . final ( ) ;
102124 }
103125
104- const re = / S u b j e c t : \[ P A T C H 1 \/ ( \d + ) \] / ;
105- const match = patch . match ( re ) ;
106- if ( ! match ) {
107- cli . warn ( 'Cannot get number of commits in the patch. ' +
108- 'It seems to be malformed' ) ;
126+ const suggestion = this . getRebaseSuggestion ( subjects ) ;
127+
128+ cli . log ( `There are ${ subjects . length } commits in the PR` ) ;
129+ cli . log ( 'Please run the following command to complete landing\n\n' +
130+ `$ ${ suggestion } # put "edit" on every commit that will stay` ) ;
131+ }
132+
133+ async apply ( ) {
134+ const { cli } = this ;
135+ if ( ! this . readyToApply ( ) ) {
136+ cli . warn ( 'This session can not proceed to apply patches, ' +
137+ 'run `git node land --abort`' ) ;
109138 return ;
110139 }
111- const { upstream, branch } = this ;
112- cli . log (
113- `There are ${ match [ 1 ] } commits in the PR.\n` +
114- `Please run \`git rebase ${ upstream } /${ branch } -i\`, put "edit" on ` +
115- 'every commit that\'s gonna stay and use `git node land --amend` to ' +
116- 'amend the commit messages' ) ;
117- // TODO: do git rebase automatically?
140+ await this . tryResetBranch ( ) ;
141+
142+ const patch = await this . downloadAndPatch ( ) ;
143+ this . startAmending ( ) ;
144+ await this . suggestAfterPatch ( patch ) ;
118145 }
119146
120147 getCurrentRev ( ) {
@@ -166,17 +193,17 @@ class LandingSession extends Session {
166193 cli . log ( `Please manually edit ${ messageFile } , then run\n` +
167194 `\`git commit --amend -F ${ messageFile } \` ` +
168195 'to finish amending the message' ) ;
169- return false ;
196+ process . exit ( 1 ) ; // make it work with git rebase -x
170197 }
171198
172199 async final ( ) {
173- const { cli } = this ;
200+ const { cli, owner, repo, upstream, branch, prid } = this ;
201+
174202 if ( ! this . readyToFinal ( ) ) { // check git rebase/am has been done
175203 cli . warn ( 'Not yet ready to final' ) ;
176204 return ;
177- }
178- const upstream = this . upstream ;
179- const branch = this . branch ;
205+ } ;
206+
180207 const notYetPushed = this . getNotYetPushedCommits ( ) ;
181208 const notYetPushedVerbose = this . getNotYetPushedCommits ( true ) ;
182209 const validateCommand = path . join (
@@ -196,9 +223,11 @@ class LandingSession extends Session {
196223 const head = this . getUpstreamHead ( ) . slice ( 0 , 7 ) ;
197224 willBeLanded = `${ head } ...${ willBeLanded } ` ;
198225 }
226+
199227 cli . log ( 'To finish landing:' ) ;
200228 cli . log ( `1. Run \`git push ${ upstream } ${ branch } \`` ) ;
201- cli . log ( `2. Post in the PR: \`Landed in ${ willBeLanded } \`` ) ;
229+ const url = `https://github.com/${ owner } /${ repo } /pull/${ prid } ` ;
230+ cli . log ( `2. Post in ${ url } : \`Landed in ${ willBeLanded } \`` ) ;
202231
203232 const shouldClean = await cli . prompt ( 'Clean up generated temporary files?' ) ;
204233 if ( shouldClean ) {
0 commit comments