@@ -158,6 +158,12 @@ fn show_version() {
158
158
println ! ( "{}" , env!( "CARGO_PKG_VERSION" ) ) ;
159
159
}
160
160
161
+ // FIXME: false positive for needless_lifetimes
162
+ #[ allow( needless_lifetimes) ]
163
+ fn has_prefix < ' a , T : PartialEq , I : Iterator < Item = & ' a T > > ( v : & ' a [ T ] , itr : I ) -> bool {
164
+ v. iter ( ) . zip ( itr) . all ( |( a, b) | a == b)
165
+ }
166
+
161
167
pub fn main ( ) {
162
168
use std:: env;
163
169
@@ -192,26 +198,48 @@ pub fn main() {
192
198
193
199
let manifest_path = manifest_path_arg. map ( |arg| PathBuf :: from ( Path :: new ( & arg[ "--manifest-path=" . len ( ) ..] ) ) ) ;
194
200
195
- let current_dir = std:: env:: current_dir ( ) ;
201
+ let package_index = {
202
+ let mut iterator = metadata. packages . iter ( ) ;
196
203
197
- let package_index = metadata
198
- . packages
199
- . iter ( )
200
- . position ( |package| {
201
- let package_manifest_path = Path :: new ( & package. manifest_path ) ;
202
204
if let Some ( ref manifest_path) = manifest_path {
203
- package_manifest_path == manifest_path
205
+ iterator. position ( |package| {
206
+ let package_manifest_path = Path :: new ( & package. manifest_path ) ;
207
+ package_manifest_path == manifest_path
208
+ } )
204
209
} else {
205
- let current_dir = current_dir
206
- . as_ref ( )
207
- . expect ( "could not read current directory" ) ;
208
- let package_manifest_directory = package_manifest_path
209
- . parent ( )
210
- . expect ( "could not find parent directory of package manifest" ) ;
211
- package_manifest_directory == current_dir
210
+ let current_dir = std:: env:: current_dir ( )
211
+ . expect ( "could not read current directory" )
212
+ . canonicalize ( )
213
+ . expect ( "current directory cannot be canonicalized" ) ;
214
+ let current_dir_components = current_dir. components ( ) . collect :: < Vec < _ > > ( ) ;
215
+
216
+ // This gets the most-recent parent (the one that takes the fewest `cd ..`s to
217
+ // reach).
218
+ iterator
219
+ . enumerate ( )
220
+ . filter_map ( |( i, package) | {
221
+ let package_manifest_path = Path :: new ( & package. manifest_path ) ;
222
+ let canonical_path = package_manifest_path
223
+ . parent ( )
224
+ . expect ( "could not find parent directory of package manifest" )
225
+ . canonicalize ( )
226
+ . expect ( "package directory cannot be canonicalized" ) ;
227
+
228
+ // TODO: We can do this in `O(1)` by combining the `len` and the
229
+ // iteration.
230
+ let components = canonical_path. components ( ) . collect :: < Vec < _ > > ( ) ;
231
+ if has_prefix ( & current_dir_components, components. iter ( ) ) {
232
+ Some ( ( i, components. len ( ) ) )
233
+ } else {
234
+ None
235
+ }
236
+ } )
237
+ . max_by_key ( |& ( _, length) | length)
238
+ . map ( |( i, _) | i)
212
239
}
213
- } )
240
+ }
214
241
. expect ( "could not find matching package" ) ;
242
+
215
243
let package = metadata. packages . remove ( package_index) ;
216
244
for target in package. targets {
217
245
let args = std:: env:: args ( ) . skip ( 2 ) ;
0 commit comments