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

Unified Diff: site/try/project_server.dart

Issue 2232273004: Delete site/try (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 4 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
Index: site/try/project_server.dart
diff --git a/site/try/project_server.dart b/site/try/project_server.dart
deleted file mode 100644
index 08c5d565425f206d777c404842ecc524397d19d4..0000000000000000000000000000000000000000
--- a/site/try/project_server.dart
+++ /dev/null
@@ -1,455 +0,0 @@
-// 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.
-
-library trydart.projectServer;
-
-import 'dart:io';
-
-import 'dart:async' show
- Future,
- Stream;
-
-import 'dart:convert' show
- HtmlEscape,
- JSON,
- UTF8;
-
-class WatchHandler {
- final WebSocket socket;
-
- final Set<String> watchedFiles;
-
- static final Set<WatchHandler> handlers = new Set<WatchHandler>();
-
- static const Map<int, String> fsEventNames = const <int, String>{
- FileSystemEvent.CREATE: 'create',
- FileSystemEvent.DELETE: 'delete',
- FileSystemEvent.MODIFY: 'modify',
- FileSystemEvent.MOVE: 'move',
- };
-
- WatchHandler(this.socket, Iterable<String> watchedFiles)
- : this.watchedFiles = watchedFiles.toSet();
-
- handleFileSystemEvent(FileSystemEvent event) {
- if (event.isDirectory) return;
- String type = fsEventNames[event.type];
- if (type == null) type = 'unknown';
- String path = new Uri.file(event.path).pathSegments.last;
- shouldIgnore(type, path).then((bool ignored) {
- if (ignored) return;
- socket.add(JSON.encode({type: [path]}));
- });
- }
-
- Future<bool> shouldIgnore(String type, String path) {
- switch (type) {
- case 'create':
- return new Future<bool>.value(!watchedFiles.contains(path));
- case 'delete':
- return Conversation.listProjectFiles().then((List<String> files) {
- watchedFiles
- ..retainAll(files)
- ..addAll(files);
- return watchedFiles.contains(path);
- });
- case 'modify':
- return new Future<bool>.value(false);
- default:
- print('Unhandled fs-event for $path ($type).');
- return new Future<bool>.value(true);
- }
- }
-
- onData(_) {
- // TODO(ahe): Move POST code here?
- }
-
- onDone() {
- handlers.remove(this);
- }
-
- static handleWebSocket(WebSocket socket) {
- Conversation.ensureProjectWatcher();
- Conversation.listProjectFiles().then((List<String> files) {
- socket.add(JSON.encode({'create': files}));
- WatchHandler handler = new WatchHandler(socket, files);
- handlers.add(handler);
- socket.listen(
- handler.onData, cancelOnError: true, onDone: handler.onDone);
- });
- }
-
- static onFileSystemEvent(FileSystemEvent event) {
- for (WatchHandler handler in handlers) {
- handler.handleFileSystemEvent(event);
- }
- }
-}
-
-/// Represents a "project" command. These commands are accessed from the URL
-/// "/project?name".
-class ProjectCommand {
- final String name;
-
- /// For each query parameter, this map describes rules for validating them.
- final Map<String, String> rules;
-
- final Function handle;
-
- const ProjectCommand(this.name, this.rules, this.handle);
-}
-
-class Conversation {
- HttpRequest request;
- HttpResponse response;
-
- static const String PROJECT_PATH = '/project';
-
- static const String PACKAGES_PATH = '/packages';
-
- static const String CONTENT_TYPE = HttpHeaders.CONTENT_TYPE;
-
- static const String GIT_TAG = 'try_dart_backup';
-
- static const String COMMIT_MESSAGE = """
-Automated backup.
-
-It is safe to delete tag '$GIT_TAG' if you don't need the backup.""";
-
- static Uri documentRoot = Uri.base;
-
- static Uri projectRoot = Uri.base.resolve('site/try/src/');
-
- static Uri packageRoot = Uri.base.resolve('sdk/lib/_internal/');
-
- static const List<ProjectCommand> COMMANDS = const <ProjectCommand>[
- const ProjectCommand('list', const {'list': null}, handleProjectList),
- ];
-
- static Stream<FileSystemEvent> projectChanges;
-
- static final Map<String, String> gitEnv = computeGitEnv();
-
- Conversation(this.request, this.response);
-
- onClosed(_) {
- if (response.statusCode == HttpStatus.OK) return;
- print('Request for ${request.uri} ${response.statusCode}');
- }
-
- notFound(path) {
- response.statusCode = HttpStatus.NOT_FOUND;
- response.write(htmlInfo('Not Found',
- 'The file "$path" could not be found.'));
- response.close();
- }
-
- badRequest(String problem) {
- response.statusCode = HttpStatus.BAD_REQUEST;
- response.write(htmlInfo("Bad request",
- "Bad request '${request.uri}': $problem"));
- response.close();
- }
-
- internalError(error, stack) {
- print(error);
- if (stack != null) print(stack);
- response.statusCode = HttpStatus.INTERNAL_SERVER_ERROR;
- response.write(htmlInfo("Internal Server Error",
- "Internal Server Error: $error\n$stack"));
- response.close();
- }
-
- bool validate(Map<String, String> parameters, Map<String, String> rules) {
- Iterable<String> problems = rules.keys
- .where((name) => !parameters.containsKey(name))
- .map((name) => "Missing parameter: '$name'.");
- if (!problems.isEmpty) {
- badRequest(problems.first);
- return false;
- }
- Set extra = new Set.from(parameters.keys)..removeAll(rules.keys);
- if (extra.isEmpty) return true;
- String extraString = (extra.toList()..sort()).join("', '");
- badRequest("Extra parameters: '$extraString'.");
- return false;
- }
-
- static Future<List<String>> listProjectFiles() {
- String nativeDir = projectRoot.toFilePath();
- Directory dir = new Directory(nativeDir);
- var future = dir.list(recursive: true, followLinks: false).toList();
- return future.then((List<FileSystemEntity> entries) {
- return entries
- .map((e) => e.path)
- .where((p) => p.endsWith('.dart') && p.startsWith(nativeDir))
- .map((p) => p.substring(nativeDir.length))
- .map((p) => new Uri.file(p).path).toList();
- });
- }
-
- static handleProjectList(Conversation self) {
- listProjectFiles().then((List<String> files) {
- self.response
- ..write(JSON.encode(files))
- ..close();
- });
- }
-
- handleProjectRequest() {
- Map<String, String> parameters = request.uri.queryParameters;
- for (ProjectCommand command in COMMANDS) {
- if (parameters.containsKey(command.name)) {
- if (validate(parameters, command.rules)) {
- (command.handle)(this);
- }
- return;
- }
- }
- String commands = COMMANDS.map((c) => c.name).join("', '");
- badRequest("Valid commands are: '$commands'");
- }
-
- handleSocket() {
- if (request.uri.path == '/ws/watch') {
- WebSocketTransformer.upgrade(request).then(WatchHandler.handleWebSocket);
- } else {
- response.done
- .then(onClosed)
- .catchError(onError);
- notFound(request.uri.path);
- }
- }
-
- handle() {
- response.done
- .then(onClosed)
- .catchError(onError);
-
- Uri uri = request.uri;
- if (uri.path == PROJECT_PATH) {
- return handleProjectRequest();
- }
- if (uri.path.endsWith('/')) {
- uri = uri.resolve('index.html');
- }
- if (uri.path == '/css/fonts/fontawesome-webfont.woff') {
- uri = uri.resolve('/fontawesome-webfont.woff');
- }
- if (uri.path.contains('..') || uri.path.contains('%')) {
- return notFound(uri.path);
- }
- String path = uri.path;
- Uri root = documentRoot;
- String dartType = 'application/dart';
- if (path.startsWith('/project/packages/')) {
- root = packageRoot;
- path = path.substring('/project/packages'.length);
- } else if (path.startsWith('${PROJECT_PATH}/')) {
- root = projectRoot;
- path = path.substring(PROJECT_PATH.length);
- dartType = 'text/plain';
- } else if (path.startsWith('${PACKAGES_PATH}/')) {
- root = packageRoot;
- path = path.substring(PACKAGES_PATH.length);
- }
-
- String filePath = root.resolve('.$path').toFilePath();
- switch (request.method) {
- case 'GET':
- return handleGet(filePath, dartType);
- case 'POST':
- return handlePost(filePath);
- default:
- String method = const HtmlEscape().convert(request.method);
- return badRequest("Unsupported method: '$method'");
- }
- }
-
- void handleGet(String path, String dartType) {
- var f = new File(path);
- f.exists().then((bool exists) {
- if (!exists) return notFound(request.uri);
- if (path.endsWith('.html')) {
- response.headers.set(CONTENT_TYPE, 'text/html');
- } else if (path.endsWith('.dart')) {
- response.headers.set(CONTENT_TYPE, dartType);
- } else if (path.endsWith('.js')) {
- response.headers.set(CONTENT_TYPE, 'application/javascript');
- } else if (path.endsWith('.ico')) {
- response.headers.set(CONTENT_TYPE, 'image/x-icon');
- } else if (path.endsWith('.appcache')) {
- response.headers.set(CONTENT_TYPE, 'text/cache-manifest');
- }
- f.openRead().pipe(response).catchError(onError);
- });
- }
-
- handlePost(String path) {
- // The data is sent using a dart:html HttpRequest (aka XMLHttpRequest).
- // According to http://xhr.spec.whatwg.org/, strings are always encoded as
- // UTF-8.
- request.transform(UTF8.decoder).join().then((String data) {
- // The rest of this method is synchronous. This guarantees that we don't
- // make conflicting git changes in response to multiple POST requests.
- try {
- backup(path);
- } catch (e, stack) {
- return internalError(e, stack);
- }
-
- new File(path).writeAsStringSync(data);
-
- response
- ..statusCode = HttpStatus.OK
- ..close();
- });
- }
-
- // Back up the file [path] using git.
- static void backup(String path) {
- // Reset the index.
- git('read-tree', ['HEAD']);
-
- // Save modifications in index.
- git('update-index', ['--add', path]);
-
- // If the file isn't modified, don't back it up.
- if (checkGit('diff', ['--cached', '--quiet'])) return;
-
- String localModifications = git('write-tree');
-
- String tag = 'refs/tags/$GIT_TAG';
- var arguments = ['-m', COMMIT_MESSAGE, localModifications];
-
- if (checkGit('rev-parse', ['-q', '--verify', tag])) {
- // The tag already exists.
-
- if (checkGit('diff-tree', ['--quiet', localModifications, tag])) {
- // localModifications are identical to the last backup.
- return;
- }
-
- // Use the tag as a parent.
- arguments = ['-p', tag]..addAll(arguments);
-
- String headCommit = git('rev-parse', ['HEAD']);
- String mergeBase = git('merge-base', [tag, 'HEAD']);
- if (headCommit != mergeBase) {
- arguments = ['-p', 'HEAD']..addAll(arguments);
- }
- } else {
- arguments = ['-p', 'HEAD']..addAll(arguments);
- }
-
- // Commit the local modifcations.
- String commit = git('commit-tree', arguments);
-
- // Create or update the tag.
- git('tag', ['-f', GIT_TAG, commit]);
- }
-
- static String git(String command,
- [List<String> arguments = const <String> []]) {
- ProcessResult result =
- run('git', <String>[command]..addAll(arguments), gitEnv);
- if (result.exitCode != 0) {
- throw 'git error: ${result.stdout}\n${result.stderr}';
- }
- return result.stdout.trim();
- }
-
- static bool checkGit(String command,
- [List<String> arguments = const <String> []]) {
- return
- run('git', <String>[command]..addAll(arguments), gitEnv).exitCode == 0;
- }
-
- static Map<String, String> computeGitEnv() {
- ProcessResult result = run('git', ['rev-parse', '--git-dir'], null);
- if (result.exitCode != 0) {
- throw 'git error: ${result.stdout}\n${result.stderr}';
- }
- String gitDir = result.stdout.trim();
- return <String, String>{ 'GIT_INDEX_FILE': '$gitDir/try_dart_backup' };
- }
-
- static ProcessResult run(String executable,
- List<String> arguments,
- Map<String, String> environment) {
- // print('Running $executable ${arguments.join(" ")}');
- return Process.runSync(executable, arguments, environment: environment);
- }
-
- static onRequest(HttpRequest request) {
- Conversation conversation = new Conversation(request, request.response);
- if (WebSocketTransformer.isUpgradeRequest(request)) {
- conversation.handleSocket();
- } else {
- conversation.handle();
- }
- }
-
- static ensureProjectWatcher() {
- if (projectChanges != null) return;
- String nativeDir = projectRoot.toFilePath();
- Directory dir = new Directory(nativeDir);
- projectChanges = dir.watch();
- projectChanges.listen(WatchHandler.onFileSystemEvent);
- }
-
- static onError(error) {
- if (error is HttpException) {
- print('Error: ${error.message}');
- } else {
- print('Error: ${error}');
- }
- }
-
- String htmlInfo(String title, String text) {
- // No script injection, please.
- title = const HtmlEscape().convert(title);
- text = const HtmlEscape().convert(text);
- return """
-<!DOCTYPE html>
-<html lang='en'>
-<head>
-<title>$title</title>
-</head>
-<body>
-<h1>$title</h1>
-<p style='white-space:pre'>$text</p>
-</body>
-</html>
-""";
- }
-}
-
-main(List<String> arguments) {
- if (arguments.length > 0) {
- Conversation.documentRoot = Uri.base.resolve(arguments[0]);
- }
- var host = '127.0.0.1';
- if (arguments.length > 1) {
- host = arguments[1];
- }
- int port = 0;
- if (arguments.length > 2) {
- port = int.parse(arguments[2]);
- }
- if (arguments.length > 3) {
- Conversation.projectRoot = Uri.base.resolve(arguments[3]);
- }
- if (arguments.length > 4) {
- Conversation.packageRoot = Uri.base.resolve(arguments[4]);
- }
- HttpServer.bind(host, port).then((HttpServer server) {
- print('HTTP server started on http://$host:${server.port}/');
- server.listen(Conversation.onRequest, onError: Conversation.onError);
- }).catchError((e) {
- print("HttpServer.bind error: $e");
- exit(1);
- });
-}

Powered by Google App Engine
This is Rietveld 408576698