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

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

Issue 11959011: Fix Path.relativeTo in special case where base is a substring of this. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Fixed another bug - added tests for it. Created 7 years, 11 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 | « sdk/lib/_internal/dartdoc/lib/dartdoc.dart ('k') | 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 27 matching lines...) Expand all
38 } 38 }
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 // Throws exception if an unimplemented or impossible case is reached.
49 // Returns a path "relative" such that 48 // Returns a path "relative" such that
50 // base.join(relative) == this.canonicalize. 49 // base.join(relative) == this.canonicalize.
51 // Throws an exception if no such path exists, or the case is not 50 // Throws exception if an impossible case is reached.
52 // implemented yet. 51 if (base.isAbsolute != isAbsolute ||
52 base.isWindowsShare != isWindowsShare) {
53 throw new ArgumentError(
54 "Invalid case of Path.relativeTo(base):\n"
55 " Path and base must both be relative, or both absolute.\n"
56 " Arguments: $_path.relativeTo($base)");
57 }
58
53 var basePath = base.toString(); 59 var basePath = base.toString();
54 if (base.isAbsolute && _path.startsWith(basePath) && 60 if (_path.startsWith(basePath)) {
55 base.isWindowsShare == isWindowsShare) {
56 if (_path == basePath) return new Path('.'); 61 if (_path == basePath) return new Path('.');
57 if (base.hasTrailingSeparator) { 62 // There must be a '/' at the end of the match, or immediately after.
58 return new Path(_path.substring(basePath.length)); 63 int matchEnd = basePath.length;
64 if (_path[matchEnd - 1] == '/' || _path[matchEnd] == '/') {
65 // Drop any extra '/' characters at matchEnd
66 while (matchEnd < _path.length && _path[matchEnd] == '/') {
67 matchEnd++;
68 }
69 return new Path(_path.substring(matchEnd)).canonicalize();
59 } 70 }
60 if (_path[basePath.length] == '/') { 71 }
61 return new Path(_path.substring(basePath.length + 1));
62 }
63 } else if (base.isAbsolute == isAbsolute &&
64 base.isWindowsShare == isWindowsShare) {
65 List<String> baseSegments = base.canonicalize().segments();
66 List<String> pathSegments = canonicalize().segments();
67 if (baseSegments.length == 1 && baseSegments[0] == '.') {
68 baseSegments = [];
69 }
70 if (pathSegments.length == 1 && pathSegments[0] == '.') {
71 pathSegments = [];
72 }
73 int common = 0;
74 int length = min(pathSegments.length, baseSegments.length);
75 while (common < length && pathSegments[common] == baseSegments[common]) {
76 common++;
77 }
78 final segments = new List<String>();
79 72
80 if (common < baseSegments.length && baseSegments[common] == '..') { 73 List<String> baseSegments = base.canonicalize().segments();
81 throw new ArgumentError( 74 List<String> pathSegments = canonicalize().segments();
82 "Invalid case of Path.relativeTo(base):\n" 75 if (baseSegments.length == 1 && baseSegments[0] == '.') {
83 " Base path has more '..'s than path does." 76 baseSegments = [];
84 " Arguments: $_path.relativeTo($base)"); 77 }
85 } 78 if (pathSegments.length == 1 && pathSegments[0] == '.') {
86 for (int i = common; i < baseSegments.length; i++) { 79 pathSegments = [];
87 segments.add('..'); 80 }
88 } 81 int common = 0;
89 for (int i = common; i < pathSegments.length; i++) { 82 int length = min(pathSegments.length, baseSegments.length);
90 segments.add('${pathSegments[i]}'); 83 while (common < length && pathSegments[common] == baseSegments[common]) {
91 } 84 common++;
92 if (segments.isEmpty) { 85 }
93 segments.add('.'); 86 final segments = new List<String>();
94 } 87
95 if (hasTrailingSeparator) { 88 if (common < baseSegments.length && baseSegments[common] == '..') {
89 throw new ArgumentError(
90 "Invalid case of Path.relativeTo(base):\n"
91 " Base path has more '..'s than path does."
92 " Arguments: $_path.relativeTo($base)");
93 }
94 for (int i = common; i < baseSegments.length; i++) {
95 segments.add('..');
96 }
97 for (int i = common; i < pathSegments.length; i++) {
98 segments.add('${pathSegments[i]}');
99 }
100 if (segments.isEmpty) {
101 segments.add('.');
102 }
103 if (hasTrailingSeparator) {
96 segments.add(''); 104 segments.add('');
97 }
98 return new Path(Strings.join(segments, '/'));
99 } 105 }
100 throw new ArgumentError( 106 return new Path(Strings.join(segments, '/'));
101 "Invalid case of Path.relativeTo(base):\n"
102 " Path and base must both be relative, or both absolute.\n"
103 " Arguments: $_path.relativeTo($base)");
104 } 107 }
105 108
109
106 Path join(Path further) { 110 Path join(Path further) {
107 if (further.isAbsolute) { 111 if (further.isAbsolute) {
108 throw new ArgumentError( 112 throw new ArgumentError(
109 "Path.join called with absolute Path as argument."); 113 "Path.join called with absolute Path as argument.");
110 } 114 }
111 if (isEmpty) { 115 if (isEmpty) {
112 return further.canonicalize(); 116 return further.canonicalize();
113 } 117 }
114 if (hasTrailingSeparator) { 118 if (hasTrailingSeparator) {
115 var joined = new _Path._internal('$_path${further}', isWindowsShare); 119 var joined = new _Path._internal('$_path${further}', isWindowsShare);
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after
264 while (pos > 0 && _path[pos - 1] == '/') --pos; 268 while (pos > 0 && _path[pos - 1] == '/') --pos;
265 var dirPath = (pos > 0) ? _path.substring(0, pos) : '/'; 269 var dirPath = (pos > 0) ? _path.substring(0, pos) : '/';
266 return new _Path._internal(dirPath, isWindowsShare); 270 return new _Path._internal(dirPath, isWindowsShare);
267 } 271 }
268 272
269 String get filename { 273 String get filename {
270 int pos = _path.lastIndexOf('/'); 274 int pos = _path.lastIndexOf('/');
271 return _path.substring(pos + 1); 275 return _path.substring(pos + 1);
272 } 276 }
273 } 277 }
OLDNEW
« no previous file with comments | « sdk/lib/_internal/dartdoc/lib/dartdoc.dart ('k') | tests/standalone/io/path_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698