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

Side by Side 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « utils/pub/command_update.dart ('k') | utils/pub/package.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
3 // BSD-style license that can be found in the LICENSE file.
4
5 /**
6 * Helper functionality to make working with IO easier.
7 */
8 #library('pub_io');
9
10 #import('dart:io');
11
12 #import('../lib/file_system.dart', prefix: 'fs');
13
14 /**
15 * Joins a number of path string parts into a single path. Handles
16 * platform-specific path separators. Parts can be [String], [Directory], or
17 * [File] objects.
18 */
19 String join(part1, [part2, part3, part4]) {
20 final parts = _getPath(part1).split('/');
21
22 for (final part in [part2, part3, part4]) {
23 if (part == null) continue;
24
25 for (final piece in _getPath(part).split('/')) {
26 if (piece == '..' && parts.length > 0 &&
27 parts.last() != '.' && parts.last() != '..') {
28 parts.removeLast();
29 } else if (piece != '') {
30 if (parts.length > 0 && parts.last() == '.') {
31 parts.removeLast();
32 }
33 parts.add(piece);
34 }
35 }
36 }
37
38 return Strings.join(parts, Platform.pathSeparator());
39 }
40
41 /**
42 * Gets the basename, the file name without any leading directory path, for
43 * [file], which can either be a [String], [File], or [Directory].
44 */
45 String basename(file) {
46 return fs.basename(_getPath(file));
47 }
48
49 /**
50 * Reads the contents of the text file [file], which can either be a [String] or
51 * a [File].
52 */
53 Future<String> readTextFile(file) {
54 file = new File(_getPath(file));
55 final completer = new Completer<String>();
56 file.onError = (error) => completer.completeException(error);
57 file.readAsText(Encoding.UTF_8, (text) => completer.complete(text));
58
59 return completer.future;
60 }
61
62 /**
63 * Creates [file] (which can either be a [String] or a [File]), and writes
64 * [contents] to it. Completes when the file is written and closed.
65 */
66 Future<File> writeTextFile(file, String contents) {
67 file = new File(_getPath(file));
68 final completer = new Completer<File>();
69 file.onError = (error) => completer.completeException(error);
70 file.open(FileMode.WRITE, (opened) {
71 opened.onError = (error) => completer.completeException(error);
72 opened.onNoPendingWrites = () {
73 opened.close(() => completer.complete(file));
74 };
75 opened.writeString(contents);
76 });
77
78 return completer.future;
79 }
80
81 /**
82 * Creates a directory [dir]. Returns a [Future] that completes when the
83 * directory is created.
84 */
85 Future<Directory> createDir(dir) {
86 final completer = new Completer<Directory>();
87 dir = _getDirectory(dir);
88 dir.onError = (error) => completer.completeException(error);
89 dir.create(() => completer.complete(dir));
90
91 return completer.future;
92 }
93
94 /**
95 * Creates a temp directory whose name will be based on [dir] with a unique
96 * suffix appended to it. Returns a [Future] that completes when the directory
97 * is created.
98 */
99 Future<Directory> createTempDir(dir) {
100 final completer = new Completer<Directory>();
101 dir = _getDirectory(dir);
102 dir.onError = (error) => completer.completeException(error);
103 dir.createTemp(() => completer.complete(dir));
104
105 return completer.future;
106 }
107
108 /**
109 * Asynchronously recursively deletes [dir], which can be a [String] or a
110 * [Directory]. Returns a [Future] that completes when the deletion is done.
111 */
112 Future<Directory> deleteDir(dir) {
113 final completer = new Completer<Directory>();
114 dir = _getDirectory(dir);
115 dir.onError = (error) => completer.completeException(error);
116 dir.deleteRecursively(() => completer.complete(dir));
117
118 return completer.future;
119 }
120
121 /**
122 * Asynchronously lists the contents of [dir], which can be a [String] directory
123 * path or a [Directory]. If [recursive] is `true`, lists subdirectory contents
124 * (defaults to `false`). If [includeSpecialFiles] is `true`, includes
125 * hidden `.DS_Store` files (defaults to `false`, other hidden files may be
126 * omitted later).
127 */
128 Future<List<String>> listDir(dir,
129 [bool recursive = false, bool includeSpecialFiles = false]) {
130 final completer = new Completer<List<String>>();
131 final contents = <String>[];
132
133 dir = _getDirectory(dir);
134
135 dir.onDone = (done) {
136 // TODO(rnystrom): May need to sort here if it turns out onDir and onFile
137 // aren't guaranteed to be called in a certain order. So far, they seem to.
138 if (done) completer.complete(contents);
139 };
140
141 dir.onError = (error) => completer.completeException(error);
142 dir.onDir = (file) => contents.add(file);
143 dir.onFile = (file) {
144 if (!includeSpecialFiles) {
145 if (basename(file) == '.DS_Store') return;
146 }
147 contents.add(file);
148 };
149
150 dir.list(recursive: recursive);
151
152 return completer.future;
153 }
154
155 /**
156 * Spawns and runs the process located at [executable], passing in [args].
157 * Returns a [Future] that will complete the results of the process after it
158 * has ended.
159 */
160 Future<ProcessResult> runProcess(String executable, List<String> args) {
161 int exitCode;
162
163 final process = new Process.start(executable, args);
164
165 final outStream = new StringInputStream(process.stdout);
166 final processStdout = <String>[];
167
168 final errStream = new StringInputStream(process.stderr);
169 final processStderr = <String>[];
170
171 final completer = new Completer<ProcessResult>();
172
173 checkComplete() {
174 // Wait until the process is done and its output streams are closed.
175 if (!outStream.closed) return;
176 if (!errStream.closed) return;
177 if (exitCode == null) return;
178
179 completer.complete(new ProcessResult(
180 processStdout, processStderr, exitCode));
181 }
182
183 outStream.onLine = () => processStdout.add(outStream.readLine());
184 outStream.onClosed = checkComplete;
185 outStream.onError = (error) => completer.completeException(error);
186
187 errStream.onLine = () => processStderr.add(errStream.readLine());
188 errStream.onClosed = checkComplete;
189 errStream.onError = (error) => completer.completeException(error);
190
191 process.onExit = (actualExitCode) {
192 exitCode = actualExitCode;
193 checkComplete();
194 };
195
196 process.onError = (error) => completer.completeException(error);
197
198 return completer.future;
199 }
200
201 /**
202 * Contains the results of invoking a [Process] and waiting for it to complete.
203 */
204 class ProcessResult {
205 final List<String> stdout;
206 final List<String> stderr;
207 final int exitCode;
208
209 const ProcessResult(this.stdout, this.stderr, this.exitCode);
210 }
211
212 /**
213 * Gets the path string for [entry], which can either already be a path string,
214 * or be a [File] or [Directory]. Allows working generically with "file-like"
215 * objects.
216 */
217 String _getPath(entry) {
218 if (entry is String) return entry;
219 if (entry is File) return entry.name;
220 if (entry is Directory) return entry.path;
221 throw 'Entry $entry is not a supported type.';
222 }
223
224 /**
225 * Gets a [Directory] for [entry], which can either already be one, or be a
226 * [String].
227 */
228 Directory _getDirectory(entry) {
229 if (entry is Directory) return entry;
230 return new Directory(entry);
231 }
OLDNEW
« 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