Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(6)

Side by Side Diff: lib/src/package.dart

Issue 1862833002: Resolve symlinks when publishing from Git repos. (Closed) Base URL: git@github.com:dart-lang/pub.git@master
Patch Set: Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698