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