OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 import 'dart:io'; | 5 import 'dart:io'; |
6 | 6 |
7 import 'package:barback/barback.dart'; | 7 import 'package:barback/barback.dart'; |
8 import 'package:path/path.dart' as p; | 8 import 'package:path/path.dart' as p; |
9 import 'package:pub_semver/pub_semver.dart'; | 9 import 'package:pub_semver/pub_semver.dart'; |
10 | 10 |
(...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
245 relativeBeneath.length + 1; | 245 relativeBeneath.length + 1; |
246 files = files.where((file) => !file.contains('/', relativeStart)); | 246 files = files.where((file) => !file.contains('/', relativeStart)); |
247 } | 247 } |
248 | 248 |
249 // Git always prints files relative to the repository root, but we want | 249 // Git always prints files relative to the repository root, but we want |
250 // them relative to the working directory. It also prints forward slashes | 250 // them relative to the working directory. It also prints forward slashes |
251 // on Windows which we normalize away for easier testing. | 251 // on Windows which we normalize away for easier testing. |
252 files = files.map((file) { | 252 files = files.map((file) { |
253 if (Platform.operatingSystem != 'windows') return "$dir/$file"; | 253 if (Platform.operatingSystem != 'windows') return "$dir/$file"; |
254 return "$dir\\${file.replaceAll("/", "\\")}"; | 254 return "$dir\\${file.replaceAll("/", "\\")}"; |
255 }).where((file) { | 255 }).expand((file) { |
256 // Filter out broken symlinks, since git doesn't do so automatically. | 256 if (fileExists(file)) return [file]; |
257 return fileExists(file); | 257 if (!dirExists(file)) return []; |
| 258 |
| 259 // `git ls-files` only returns files, except in the case of a symlink to |
| 260 // a directory. So if we're here, [file] refers to a valid symlink to a |
| 261 // directory. |
| 262 return recursive ? _listSymlinkedDir(file) : [file]; |
258 }); | 263 }); |
259 } else { | 264 } else { |
260 files = listDir(beneath, recursive: recursive, includeDirs: false, | 265 files = listDir(beneath, recursive: recursive, includeDirs: false, |
261 whitelist: _WHITELISTED_FILES); | 266 whitelist: _WHITELISTED_FILES); |
262 } | 267 } |
263 | 268 |
264 return files.where((file) { | 269 return files.where((file) { |
265 // Using substring here is generally problematic in cases where dir has | 270 // Using substring here is generally problematic in cases where dir has |
266 // one or more trailing slashes. If you do listDir("foo"), you'll get back | 271 // one or more trailing slashes. If you do listDir("foo"), you'll get back |
267 // paths like "foo/bar". If you do listDir("foo/"), you'll get "foo/bar" | 272 // paths like "foo/bar". If you do listDir("foo/"), you'll get "foo/bar" |
268 // (note the trailing slash was dropped. If you do listDir("foo//"), | 273 // (note the trailing slash was dropped. If you do listDir("foo//"), |
269 // you'll get "foo//bar". | 274 // you'll get "foo//bar". |
270 // | 275 // |
271 // This means if you strip off the prefix, the resulting string may have a | 276 // This means if you strip off the prefix, the resulting string may have a |
272 // leading separator (if the prefix did not have a trailing one) or it may | 277 // leading separator (if the prefix did not have a trailing one) or it may |
273 // not. However, since we are only using the results of that to call | 278 // not. However, since we are only using the results of that to call |
274 // contains() on, the leading separator is harmless. | 279 // contains() on, the leading separator is harmless. |
275 assert(file.startsWith(beneath)); | 280 assert(file.startsWith(beneath)); |
276 file = file.substring(beneath.length); | 281 file = file.substring(beneath.length); |
277 return !_blacklistedFiles.any(file.endsWith) && | 282 return !_blacklistedFiles.any(file.endsWith) && |
278 !_blacklistedDirs.any(file.contains); | 283 !_blacklistedDirs.any(file.contains); |
279 }).toList(); | 284 }).toList(); |
280 } | 285 } |
281 | 286 |
| 287 /// List all files recursively beneath [link], which should be a symlink to a |
| 288 /// directory. |
| 289 /// |
| 290 /// This is used by [list] when listing a Git repository, since `git ls-files` |
| 291 /// can't natively follow symlinks. |
| 292 Iterable<String> _listSymlinkedDir(String link) { |
| 293 assert(linkExists(link)); |
| 294 assert(dirExists(link)); |
| 295 assert(p.isWithin(dir, link)); |
| 296 |
| 297 var target = new Directory(link).resolveSymbolicLinksSync(); |
| 298 |
| 299 List<String> targetFiles; |
| 300 if (p.isWithin(dir, target)) { |
| 301 // If the link points within this repo, use git to list the target |
| 302 // location so we respect .gitignore. |
| 303 targetFiles = listFiles( |
| 304 beneath: p.relative(target, from: dir), |
| 305 recursive: true, |
| 306 useGitIgnore: true); |
| 307 } else { |
| 308 // If the link points outside this repo, just use the default listing |
| 309 // logic. |
| 310 targetFiles = listDir(target, recursive: true, includeDirs: false, |
| 311 whitelist: _WHITELISTED_FILES); |
| 312 } |
| 313 |
| 314 // Re-write the paths so they're underneath the symlink. |
| 315 return targetFiles.map((targetFile) => |
| 316 p.join(link, p.relative(targetFile, from: target))); |
| 317 } |
| 318 |
282 /// Returns a debug string for the package. | 319 /// Returns a debug string for the package. |
283 String toString() => '$name $version ($dir)'; | 320 String toString() => '$name $version ($dir)'; |
284 } | 321 } |
285 | 322 |
286 /// This is the private base class of [PackageRef], [PackageID], and | 323 /// This is the private base class of [PackageRef], [PackageID], and |
287 /// [PackageDep]. | 324 /// [PackageDep]. |
288 /// | 325 /// |
289 /// It contains functionality and state that those classes share but is private | 326 /// It contains functionality and state that those classes share but is private |
290 /// so that from outside of this library, there is no type relationship between | 327 /// so that from outside of this library, there is no type relationship between |
291 /// those three types. | 328 /// those three types. |
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
449 | 486 |
450 bool operator ==(other) { | 487 bool operator ==(other) { |
451 // TODO(rnystrom): We're assuming here that we don't need to delve into the | 488 // TODO(rnystrom): We're assuming here that we don't need to delve into the |
452 // description. | 489 // description. |
453 return other is PackageDep && | 490 return other is PackageDep && |
454 other.name == name && | 491 other.name == name && |
455 other.source == source && | 492 other.source == source && |
456 other.constraint == constraint; | 493 other.constraint == constraint; |
457 } | 494 } |
458 } | 495 } |
OLD | NEW |