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

Side by Side Diff: sdk/lib/io/path_impl.dart

Issue 12662010: dart:io | Handle drive letters in Path.relativeTo on Windows. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Fix bugs. Created 7 years, 9 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 | Annotate | Revision Log
« no previous file with comments | « no previous file | tests/standalone/io/path_test.dart » ('j') | 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 part of dart.io; 5 part of dart.io;
6 6
7 class _Path implements Path { 7 class _Path implements Path {
8 final String _path; 8 final String _path;
9 final bool isWindowsShare; 9 final bool isWindowsShare;
10 10
(...skipping 28 matching lines...) Expand all
39 39
40 int get hashCode => _path.hashCode; 40 int get hashCode => _path.hashCode;
41 bool get isEmpty => _path.isEmpty; 41 bool get isEmpty => _path.isEmpty;
42 bool get isAbsolute => _path.startsWith('/'); 42 bool get isAbsolute => _path.startsWith('/');
43 bool get hasTrailingSeparator => _path.endsWith('/'); 43 bool get hasTrailingSeparator => _path.endsWith('/');
44 44
45 String toString() => _path; 45 String toString() => _path;
46 46
47 Path relativeTo(Path base) { 47 Path relativeTo(Path base) {
48 // Returns a path "relative" such that 48 // Returns a path "relative" such that
49 // base.join(relative) == this.canonicalize. 49 // base.join(relative) == this.canonicalize.
50 // Throws exception if an impossible case is reached. 50 // Throws exception if an impossible case is reached.
51 if (base.isAbsolute != isAbsolute || 51 if (base.isAbsolute != isAbsolute ||
52 base.isWindowsShare != isWindowsShare) { 52 base.isWindowsShare != isWindowsShare) {
53 throw new ArgumentError( 53 throw new ArgumentError("""
Søren Gjesse 2013/03/14 13:53:32 Please keep using concatenation of adjacent string
54 "Invalid case of Path.relativeTo(base):\n" 54 Invalid case of Path.relativeTo(base):
55 " Path and base must both be relative, or both absolute.\n" 55 Path and base must both be relative, or both absolute.
56 " Arguments: $_path.relativeTo($base)"); 56 Arguments: $_path.relativeTo($base)""");
57 } 57 }
58 58
59 var basePath = base.toString(); 59 var basePath = base.toString();
60 // Handle drive letters specially on Windows.
61 if (base.isAbsolute && Platform.operatingSystem == 'windows') {
62 bool baseHasDrive =
63 basePath.length >= 4 && basePath[2] == ':' && basePath[3] == '/';
64 bool pathHasDrive =
65 _path.length >= 4 && _path[2] == ':' && _path[3] == '/';
66 if (baseHasDrive && pathHasDrive) {
67 int baseDrive = basePath.codeUnitAt(1) | 32; // Convert to uppercase.
68 if (baseDrive >= 'a'.codeUnitAt(0) &&
69 baseDrive <= 'z'.codeUnitAt(0) &&
70 baseDrive == (_path.codeUnitAt(1) | 32)) {
71 if(basePath[1] != _path[1]) {
72 // Replace the drive letter in basePath with that from _path.
73 basePath = '/${_path[1]}:/${basePath.substring(4)}';
74 base = new Path(basePath);
75 }
76 } else {
77 throw new ArgumentError("""
78 Invalid case of Path.relativeTo(base):
79 Base path and target path are on different Windows drives.
80 Arguments: $_path.relativeTo($base)""");
81 }
82 } else if (baseHasDrive != pathHasDrive) {
83 throw new ArgumentError("""
84 Invalid case of Path.relativeTo(base):
85 Base path must start with a drive letter if and only if target path does.
86 Arguments: $_path.relativeTo($base)""");
87 }
88
89 }
60 if (_path.startsWith(basePath)) { 90 if (_path.startsWith(basePath)) {
61 if (_path == basePath) return new Path('.'); 91 if (_path == basePath) return new Path('.');
62 // There must be a '/' at the end of the match, or immediately after. 92 // There must be a '/' at the end of the match, or immediately after.
63 int matchEnd = basePath.length; 93 int matchEnd = basePath.length;
64 if (_path[matchEnd - 1] == '/' || _path[matchEnd] == '/') { 94 if (_path[matchEnd - 1] == '/' || _path[matchEnd] == '/') {
65 // Drop any extra '/' characters at matchEnd 95 // Drop any extra '/' characters at matchEnd
66 while (matchEnd < _path.length && _path[matchEnd] == '/') { 96 while (matchEnd < _path.length && _path[matchEnd] == '/') {
67 matchEnd++; 97 matchEnd++;
68 } 98 }
69 return new Path(_path.substring(matchEnd)).canonicalize(); 99 return new Path(_path.substring(matchEnd)).canonicalize();
70 } 100 }
71 } 101 }
72 102
73 List<String> baseSegments = base.canonicalize().segments(); 103 List<String> baseSegments = base.canonicalize().segments();
74 List<String> pathSegments = canonicalize().segments(); 104 List<String> pathSegments = canonicalize().segments();
75 if (baseSegments.length == 1 && baseSegments[0] == '.') { 105 if (baseSegments.length == 1 && baseSegments[0] == '.') {
76 baseSegments = []; 106 baseSegments = [];
77 } 107 }
78 if (pathSegments.length == 1 && pathSegments[0] == '.') { 108 if (pathSegments.length == 1 && pathSegments[0] == '.') {
79 pathSegments = []; 109 pathSegments = [];
80 } 110 }
81 int common = 0; 111 int common = 0;
82 int length = min(pathSegments.length, baseSegments.length); 112 int length = min(pathSegments.length, baseSegments.length);
83 while (common < length && pathSegments[common] == baseSegments[common]) { 113 while (common < length && pathSegments[common] == baseSegments[common]) {
84 common++; 114 common++;
85 } 115 }
86 final segments = new List<String>(); 116 final segments = new List<String>();
87 117
88 if (common < baseSegments.length && baseSegments[common] == '..') { 118 if (common < baseSegments.length && baseSegments[common] == '..') {
89 throw new ArgumentError( 119 throw new ArgumentError("""
90 "Invalid case of Path.relativeTo(base):\n" 120 Invalid case of Path.relativeTo(base):
91 " Base path has more '..'s than path does." 121 Base path has more '..'s than path does.
92 " Arguments: $_path.relativeTo($base)"); 122 Arguments: $_path.relativeTo($base)""");
93 } 123 }
94 for (int i = common; i < baseSegments.length; i++) { 124 for (int i = common; i < baseSegments.length; i++) {
95 segments.add('..'); 125 segments.add('..');
96 } 126 }
97 for (int i = common; i < pathSegments.length; i++) { 127 for (int i = common; i < pathSegments.length; i++) {
98 segments.add('${pathSegments[i]}'); 128 segments.add('${pathSegments[i]}');
99 } 129 }
100 if (segments.isEmpty) { 130 if (segments.isEmpty) {
101 segments.add('.'); 131 segments.add('.');
102 } 132 }
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after
267 while (pos > 0 && _path[pos - 1] == '/') --pos; 297 while (pos > 0 && _path[pos - 1] == '/') --pos;
268 var dirPath = (pos > 0) ? _path.substring(0, pos) : '/'; 298 var dirPath = (pos > 0) ? _path.substring(0, pos) : '/';
269 return new _Path._internal(dirPath, isWindowsShare); 299 return new _Path._internal(dirPath, isWindowsShare);
270 } 300 }
271 301
272 String get filename { 302 String get filename {
273 int pos = _path.lastIndexOf('/'); 303 int pos = _path.lastIndexOf('/');
274 return _path.substring(pos + 1); 304 return _path.substring(pos + 1);
275 } 305 }
276 } 306 }
OLDNEW
« no previous file with comments | « no previous file | tests/standalone/io/path_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698