55 * LICENSE file in the root directory of this source tree.
66 */
77
8- use std:: iter:: zip;
98use std:: collections:: HashSet ;
9+ use std:: iter:: zip;
1010
1111use crate :: {
1212 error:: { add_error, Error , Result , ResultExt } ,
@@ -55,14 +55,20 @@ pub struct DiffOptions {
5555
5656fn get_oids ( refs : & str , repo : & git2:: Repository ) -> Result < HashSet < Oid > > {
5757 // refs might be a single (eg 012345abc or HEAD) or a range (HEAD~4..HEAD~2)
58- let revspec = repo. revparse ( & refs) ?;
58+ let revspec = repo. revparse ( refs) ?;
5959
60- let from = revspec. from ( ) . ok_or ( Error :: new ( "Unexpectedly no from id in range" ) ) ?. id ( ) ;
60+ let from = revspec
61+ . from ( )
62+ . ok_or ( Error :: new ( "Unexpectedly no from id in range" ) ) ?
63+ . id ( ) ;
6164 if revspec. mode ( ) . contains ( git2:: RevparseMode :: SINGLE ) {
6265 // simple case, just return the id
6366 return Ok ( HashSet :: from ( [ from] ) ) ;
6467 }
65- let to = revspec. to ( ) . ok_or ( Error :: new ( "Unexpectedly no to id in range" ) ) ?. id ( ) ;
68+ let to = revspec
69+ . to ( )
70+ . ok_or ( Error :: new ( "Unexpectedly no to id in range" ) ) ?
71+ . id ( ) ;
6672
6773 let mut walk = repo. revwalk ( ) ?;
6874 walk. push ( to) ?;
@@ -93,32 +99,47 @@ pub async fn diff(
9399 return result;
94100 } ;
95101
96- // If refs is set, we want to track which commits to run `diff`
97- // against. The simple approach would be to adjust the prepared_commits
98- // Vec (as with opts.all above). This does not work however, as we need
99- // to know the entire list (or more specifically the list after the first update)
100- // for the rewrite_commit_messages step.
101- // This is not a problem for opts.all as it only ever has a single commit to update,
102- // and so nothing after it.
103- let revs_to_pr = match ( & opts. refs , opts. all ) {
104- ( Some ( refs) , false ) => get_oids ( refs, & git. repo ( ) ) . map ( |i| Some ( i) ) ,
105- ( Some ( _) , true ) => Err ( Error :: new ( "Do not use --refs with --all" ) ) ,
106- ( None , all) => {
107- // Remove all prepared commits from the vector but the last. So, if
108- // `--all` is not given, we only operate on the HEAD commit.
109- if !all {
110- prepared_commits. drain ( 0 ..prepared_commits. len ( ) - 1 ) ;
111- }
112- Ok ( None )
102+ // If refs is set, we want to track which commits to run `diff` against. The
103+ // simple approach would be to adjust the prepared_commits Vec (as with
104+ // opts.all above). This does not work however, as we need to know the
105+ // entire list (or more specifically the list after the first update) for
106+ // the rewrite_commit_messages step. This is not a problem for opts.all as
107+ // it only ever has a single commit to update, and so nothing after it.
108+ let revs_to_pr = match ( opts. refs . as_deref ( ) , opts. all ) {
109+ ( Some ( refs) , false ) => Some ( get_oids ( refs, & git. repo ( ) ) ?) ,
110+ ( Some ( _) , true ) => {
111+ return Err ( Error :: new ( "Do not use --refs with --all" ) )
112+ }
113+ ( None , true ) => {
114+ // Operate on all commits
115+ None
116+ }
117+ ( None , false ) => {
118+ // Only operate on the HEAD commit.
119+ prepared_commits. drain ( 0 ..prepared_commits. len ( ) - 1 ) ;
120+ None
113121 }
114- } ? ;
122+ } ;
115123
116124 #[ allow( clippy:: needless_collect) ]
117125 let pull_request_tasks: Vec < _ > = prepared_commits
118126 . iter ( )
119127 . map ( |pc : & PreparedCommit | {
120- pc. pull_request_number
121- . map ( |number| tokio:: spawn ( gh. clone ( ) . get_pull_request ( number) ) )
128+ if revs_to_pr
129+ . as_ref ( )
130+ . map ( |revs| revs. contains ( & pc. oid ) )
131+ . unwrap_or ( true )
132+ {
133+ // We are going to want to look at this pull request below.
134+ pc. pull_request_number . map ( |number| {
135+ tokio:: spawn ( gh. clone ( ) . get_pull_request ( number) )
136+ } )
137+ } else {
138+ // We will be skipping this commit below, because we have as set
139+ // of commit oids to operate on, and this commit is not in
140+ // there.
141+ None
142+ }
122143 } )
123144 . collect ( ) ;
124145
@@ -131,10 +152,14 @@ pub async fn diff(
131152 break ;
132153 }
133154
134- if let Some ( revs) = & revs_to_pr {
135- if !revs. contains ( & prepared_commit. oid ) {
136- continue ;
137- }
155+ // Check whether to skip this commit because we have a hashset of oids
156+ // to operate on, but it doesn't contain this commit oid
157+ if revs_to_pr
158+ . as_ref ( )
159+ . map ( |revs| !revs. contains ( & prepared_commit. oid ) )
160+ . unwrap_or ( false )
161+ {
162+ continue ;
138163 }
139164
140165 let pull_request = if let Some ( task) = pull_request_task {
@@ -145,10 +170,11 @@ pub async fn diff(
145170
146171 write_commit_title ( prepared_commit) ?;
147172
148- // The further implementation of the diff command is in a separate function.
149- // This makes it easier to run the code to update the local commit message
150- // with all the changes that the implementation makes at the end, even if
151- // the implementation encounters an error or exits early.
173+ // The further implementation of the diff command is in a separate
174+ // function. This makes it easier to run the code to update the local
175+ // commit message with all the changes that the implementation makes at
176+ // the end, even if the implementation encounters an error or exits
177+ // early.
152178 result = diff_impl (
153179 & opts,
154180 & mut message_on_prompt,
0 commit comments