Have pkg/path track the current working directory if it changes.

R=rnystrom@google.com
BUG=11100

Review URL: https://codereview.chromium.org//58903005

git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/path@30256 260f80e4-7a28-3924-810f-c04153c831b5
diff --git a/lib/path.dart b/lib/path.dart
index e91310a..7b955e6 100644
--- a/lib/path.dart
+++ b/lib/path.dart
@@ -46,10 +46,6 @@
 /// even when the program is run on a POSIX machine.
 library path;
 
-/// An internal builder for the current OS so we can provide a straight
-/// functional interface and not require users to create one.
-final _builder = new Builder();
-
 /// A default builder for manipulating POSIX paths.
 final posix = new Builder(style: Style.posix);
 
@@ -64,6 +60,22 @@
 void _growListFront(List list, int length, fillValue) =>
   list.insertAll(0, new List.filled(length, fillValue));
 
+/// The result of [Uri.base] last time the current working directory was
+/// calculated.
+///
+/// This is used to invalidate [_cachedBuilder] when the working directory has
+/// changed since the last time a function was called.
+Uri _lastBaseUri;
+
+/// An internal builder for the current OS so we can provide a straight
+/// functional interface and not require users to create one.
+Builder get _builder {
+  if (_cachedBuilder != null && Uri.base == _lastBaseUri) return _cachedBuilder;
+  _lastBaseUri = Uri.base;
+  _cachedBuilder = new Builder();
+  return _cachedBuilder;
+}
+Builder _cachedBuilder;
 
 /// Gets the path to the current working directory.
 ///
diff --git a/test/io_test.dart b/test/io_test.dart
index 6651249..1b1bea9 100644
--- a/test/io_test.dart
+++ b/test/io_test.dart
@@ -36,4 +36,18 @@
   test('current', () {
     expect(path.current, io.Directory.current.path);
   });
+
+  test('registers changes to the working directory', () {
+    expect(path.absolute('foo/bar'),
+        equals(path.join(io.Directory.current.path, 'foo/bar')));
+
+    var sandbox = io.Directory.systemTemp.createTempSync('path_test_').path;
+    try {
+      io.Directory.current = sandbox;
+
+      expect(path.absolute('foo/bar'), equals(path.join(sandbox, 'foo/bar')));
+    } finally {
+      new io.Directory(sandbox).deleteSync(recursive: true);
+    }
+  });
 }