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

Unified Diff: utils/pub/io.dart

Issue 10091014: Start implementing pub object model. Rudimentary package cache class, and a simple pub command to l… (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Platform is static now. Created 8 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « utils/pub/command_update.dart ('k') | utils/pub/package.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: utils/pub/io.dart
diff --git a/utils/pub/io.dart b/utils/pub/io.dart
new file mode 100644
index 0000000000000000000000000000000000000000..845b5b4c60e26b9ca8b3b655bf172a9078db542f
--- /dev/null
+++ b/utils/pub/io.dart
@@ -0,0 +1,231 @@
+// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/**
+ * Helper functionality to make working with IO easier.
+ */
+#library('pub_io');
+
+#import('dart:io');
+
+#import('../lib/file_system.dart', prefix: 'fs');
+
+/**
+ * Joins a number of path string parts into a single path. Handles
+ * platform-specific path separators. Parts can be [String], [Directory], or
+ * [File] objects.
+ */
+String join(part1, [part2, part3, part4]) {
+ final parts = _getPath(part1).split('/');
+
+ for (final part in [part2, part3, part4]) {
+ if (part == null) continue;
+
+ for (final piece in _getPath(part).split('/')) {
+ if (piece == '..' && parts.length > 0 &&
+ parts.last() != '.' && parts.last() != '..') {
+ parts.removeLast();
+ } else if (piece != '') {
+ if (parts.length > 0 && parts.last() == '.') {
+ parts.removeLast();
+ }
+ parts.add(piece);
+ }
+ }
+ }
+
+ return Strings.join(parts, Platform.pathSeparator());
+}
+
+/**
+ * Gets the basename, the file name without any leading directory path, for
+ * [file], which can either be a [String], [File], or [Directory].
+ */
+String basename(file) {
+ return fs.basename(_getPath(file));
+}
+
+/**
+ * Reads the contents of the text file [file], which can either be a [String] or
+ * a [File].
+ */
+Future<String> readTextFile(file) {
+ file = new File(_getPath(file));
+ final completer = new Completer<String>();
+ file.onError = (error) => completer.completeException(error);
+ file.readAsText(Encoding.UTF_8, (text) => completer.complete(text));
+
+ return completer.future;
+}
+
+/**
+ * Creates [file] (which can either be a [String] or a [File]), and writes
+ * [contents] to it. Completes when the file is written and closed.
+ */
+Future<File> writeTextFile(file, String contents) {
+ file = new File(_getPath(file));
+ final completer = new Completer<File>();
+ file.onError = (error) => completer.completeException(error);
+ file.open(FileMode.WRITE, (opened) {
+ opened.onError = (error) => completer.completeException(error);
+ opened.onNoPendingWrites = () {
+ opened.close(() => completer.complete(file));
+ };
+ opened.writeString(contents);
+ });
+
+ return completer.future;
+}
+
+/**
+ * Creates a directory [dir]. Returns a [Future] that completes when the
+ * directory is created.
+ */
+Future<Directory> createDir(dir) {
+ final completer = new Completer<Directory>();
+ dir = _getDirectory(dir);
+ dir.onError = (error) => completer.completeException(error);
+ dir.create(() => completer.complete(dir));
+
+ return completer.future;
+}
+
+/**
+ * Creates a temp directory whose name will be based on [dir] with a unique
+ * suffix appended to it. Returns a [Future] that completes when the directory
+ * is created.
+ */
+Future<Directory> createTempDir(dir) {
+ final completer = new Completer<Directory>();
+ dir = _getDirectory(dir);
+ dir.onError = (error) => completer.completeException(error);
+ dir.createTemp(() => completer.complete(dir));
+
+ return completer.future;
+}
+
+/**
+ * Asynchronously recursively deletes [dir], which can be a [String] or a
+ * [Directory]. Returns a [Future] that completes when the deletion is done.
+ */
+Future<Directory> deleteDir(dir) {
+ final completer = new Completer<Directory>();
+ dir = _getDirectory(dir);
+ dir.onError = (error) => completer.completeException(error);
+ dir.deleteRecursively(() => completer.complete(dir));
+
+ return completer.future;
+}
+
+/**
+ * Asynchronously lists the contents of [dir], which can be a [String] directory
+ * path or a [Directory]. If [recursive] is `true`, lists subdirectory contents
+ * (defaults to `false`). If [includeSpecialFiles] is `true`, includes
+ * hidden `.DS_Store` files (defaults to `false`, other hidden files may be
+ * omitted later).
+ */
+Future<List<String>> listDir(dir,
+ [bool recursive = false, bool includeSpecialFiles = false]) {
+ final completer = new Completer<List<String>>();
+ final contents = <String>[];
+
+ dir = _getDirectory(dir);
+
+ dir.onDone = (done) {
+ // TODO(rnystrom): May need to sort here if it turns out onDir and onFile
+ // aren't guaranteed to be called in a certain order. So far, they seem to.
+ if (done) completer.complete(contents);
+ };
+
+ dir.onError = (error) => completer.completeException(error);
+ dir.onDir = (file) => contents.add(file);
+ dir.onFile = (file) {
+ if (!includeSpecialFiles) {
+ if (basename(file) == '.DS_Store') return;
+ }
+ contents.add(file);
+ };
+
+ dir.list(recursive: recursive);
+
+ return completer.future;
+}
+
+/**
+ * Spawns and runs the process located at [executable], passing in [args].
+ * Returns a [Future] that will complete the results of the process after it
+ * has ended.
+ */
+Future<ProcessResult> runProcess(String executable, List<String> args) {
+ int exitCode;
+
+ final process = new Process.start(executable, args);
+
+ final outStream = new StringInputStream(process.stdout);
+ final processStdout = <String>[];
+
+ final errStream = new StringInputStream(process.stderr);
+ final processStderr = <String>[];
+
+ final completer = new Completer<ProcessResult>();
+
+ checkComplete() {
+ // Wait until the process is done and its output streams are closed.
+ if (!outStream.closed) return;
+ if (!errStream.closed) return;
+ if (exitCode == null) return;
+
+ completer.complete(new ProcessResult(
+ processStdout, processStderr, exitCode));
+ }
+
+ outStream.onLine = () => processStdout.add(outStream.readLine());
+ outStream.onClosed = checkComplete;
+ outStream.onError = (error) => completer.completeException(error);
+
+ errStream.onLine = () => processStderr.add(errStream.readLine());
+ errStream.onClosed = checkComplete;
+ errStream.onError = (error) => completer.completeException(error);
+
+ process.onExit = (actualExitCode) {
+ exitCode = actualExitCode;
+ checkComplete();
+ };
+
+ process.onError = (error) => completer.completeException(error);
+
+ return completer.future;
+}
+
+/**
+ * Contains the results of invoking a [Process] and waiting for it to complete.
+ */
+class ProcessResult {
+ final List<String> stdout;
+ final List<String> stderr;
+ final int exitCode;
+
+ const ProcessResult(this.stdout, this.stderr, this.exitCode);
+}
+
+/**
+ * Gets the path string for [entry], which can either already be a path string,
+ * or be a [File] or [Directory]. Allows working generically with "file-like"
+ * objects.
+ */
+String _getPath(entry) {
+ if (entry is String) return entry;
+ if (entry is File) return entry.name;
+ if (entry is Directory) return entry.path;
+ throw 'Entry $entry is not a supported type.';
+}
+
+/**
+ * Gets a [Directory] for [entry], which can either already be one, or be a
+ * [String].
+ */
+Directory _getDirectory(entry) {
+ if (entry is Directory) return entry;
+ return new Directory(entry);
+}
« no previous file with comments | « utils/pub/command_update.dart ('k') | utils/pub/package.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698