Merge remote-tracking branch 'origin/master' into api-ide-profile-add-sshprvkey

pull/240/merge
Tim Robinson 2016-07-28 21:32:00 +00:00
commit 747e923550
66 zmienionych plików z 1443 dodań i 341 usunięć

5
NOTICE 100644
Wyświetl plik

@ -0,0 +1,5 @@
This product includes software developed by:
The `appendFile` functionality in `node_modules/vfs-local` is open source
software, developed by Andrew Faulring, copyright (c) 2016 Carnegie Mellon University
and licensed under the MIT license.

Wyświetl plik

@ -0,0 +1,45 @@
"use strict";
module.exports = function(options) {
var plugins = require("./client-default")(options);
// TODO: cleanup unneeded plugins?
var includes = [];
var excludes = {};
plugins.forEach(function(p) {
if (p.packagePath && p.packagePath.indexOf("c9.core/settings") >= 0) {
p.settings = "defaults";
p.template = {
user: {},
project: {},
state: {
console: {
"@maximized": true,
type: "pane",
nodes: []
}
}
};
}
else if (p.packagePath == "plugins/c9.ide.console/console") {
p.defaultState = {
type: "pane",
nodes: [{
type: "tab",
editorType: "terminal",
active: "true"
}]
};
}
});
plugins = plugins
.concat(includes)
.filter(function (p) {
return !excludes[p] && !excludes[p.packagePath];
});
return plugins;
};

Wyświetl plik

@ -563,19 +563,6 @@ module.exports = function(options) {
realRoot: true,
home: options.local ? options.home : "~"
},
"plugins/c9.ide.mount/mount",
{
packagePath: "plugins/c9.ide.mount/ftp",
curlftpfsBin: options.mount.curlftpfsBin,
fusermountBin: options.mount.fusermountBin,
ssh: options.ssh
},
{
packagePath: "plugins/c9.ide.mount/sftp",
sshfsBin: options.mount.sshfsBin,
fusermountBin: options.mount.fusermountBin,
ssh: options.ssh
},
{
packagePath: "plugins/c9.ide.upload/dragdrop",
treeAsPane: options.local

Wyświetl plik

@ -100,12 +100,12 @@ module.exports = function(config, optimist) {
console.log("and suppress this message.\n");
host = config.host = "127.0.0.1";
}
if (/:/.test(argv.auth) && !isLocalhost && !process.env.C9_HOSTNAME) {
var auth = (argv.auth + "").split(":");
if (!auth[1] && !isLocalhost && !process.env.C9_HOSTNAME) {
console.log("Warning: running Cloud9 without using HTTP authentication.");
console.log("Run using --listen localhost instead to only expose Cloud9 to localhost,");
console.log("or use -a username:password to setup HTTP authentication\n");
}
var auth = (argv.auth + "").split(":");
var plugins = [
{

Wyświetl plik

@ -0,0 +1,11 @@
module.exports = function(options, optimist) {
var config = require("./standalone")(options, optimist);
// TODO: cleanup unneeded plugins?
options.client_config = "default-terminal";
return config;
};
if (!module.parent) require("../server")([__filename].concat(process.argv.slice(2)));

Wyświetl plik

@ -2,13 +2,34 @@
set -e
cd `dirname $0`/..
# set -x
NAME=$1
URL=$2
shift
BRANCH=
URL=
for i in "$@"; do
case $i in
-b=*|--branch=*)
BRANCH="${i#*=}"
shift
;;
-u=*|--url=*)
URL="${i#*=}"
shift
;;
*)
# unknown option
;;
esac
done
if [ "$NAME" == "" ]; then
echo "add name [url]"
echo "add name [--url=git@github.com:c9/NAME.git] [--branch=master]"
exit 0
fi
echo adding name=$NAME url=$URL branch=refs/remotes/origin/$BRANCH
if [ "$URL" == "" ]; then
URL=git@github.com:c9/$NAME.git
fi
@ -28,7 +49,7 @@ else
fi
pushd $NAME
HASH=$(git rev-parse --revs-only refs/remotes/origin/master)
HASH=$(git rev-parse --revs-only refs/remotes/origin/$BRANCH)
popd
[ -f ./config.json ] || echo "{}" > ./config.json

Wyświetl plik

@ -75,19 +75,20 @@ var supportedModes = {
Elixir: ["ex|exs"],
Elm: ["elm"],
Erlang: ["erl|hrl"],
Forth: ["frt|fs|ldr"],
Forth: ["frt|fs|ldr|fth|4th"],
Fortran: ["f|f90"],
FTL: ["ftl"],
Gcode: ["gcode"],
Gherkin: ["feature"],
Gitignore: ["^.gitignore"],
Glsl: ["glsl|frag|vert"],
Gobstones: ["gbs"],
Gobstones: ["gbs"],
golang: ["go"],
Groovy: ["groovy"],
HAML: ["haml"],
Handlebars: ["hbs|handlebars|tpl|mustache"],
Haskell: ["hs"],
Haskell_Cabal: ["cabal"],
haXe: ["hx"],
HTML: ["html|htm|xhtml"],
HTML_Elixir: ["eex|html.eex"],
@ -104,7 +105,6 @@ var supportedModes = {
JSX: ["jsx"],
Julia: ["jl"],
LaTeX: ["tex|latex|ltx|bib"],
Lean: ["lean|hlean"],
LESS: ["less"],
Liquid: ["liquid"],
Lisp: ["lisp"],
@ -206,4 +206,5 @@ module.exports = {
modesByName: modesByName
};
});
});

Wyświetl plik

@ -4993,7 +4993,7 @@ dom.importCssString(".normal-mode .ace_cursor{\
}
}
}
throw Error('No such mapping.');
// throw Error('No such mapping.');
}
};

Wyświetl plik

@ -243,7 +243,7 @@ function testVim(name, run, opts, expectedFail) {
// Record for insert mode.
if (handled == "handled" && cm.state.vim.insertMode && arguments[i] != 'Esc') {
var lastChange = CodeMirror.Vim.getVimGlobalState_().macroModeState.lastInsertModeChanges;
if (lastChange) {
if (lastChange && (key.indexOf('Delete') != -1 || key.indexOf('Backspace') != -1)) {
lastChange.changes.push(new CodeMirror.Vim.InsertModeKey(key));
}
}
@ -2905,6 +2905,14 @@ testVim('._insert', function(cm, vim, helpers) {
helpers.doKeys('.');
eq('testestt', cm.getValue());
helpers.assertCursorAt(0, 6);
helpers.doKeys('O');
cm.replaceRange('xyz', cm.getCursor());
helpers.doInsertModeKeys('Backspace');
helpers.doInsertModeKeys('Down');
helpers.doKeys('<Esc>');
helpers.doKeys('.');
eq('xy\nxy\ntestestt', cm.getValue());
helpers.assertCursorAt(1, 1);
}, { value: ''});
testVim('._insert_repeat', function(cm, vim, helpers) {
helpers.doKeys('i');

Wyświetl plik

@ -94,7 +94,9 @@
["keyword.operator","-"],
["identifier","o"],
["text"," "],
["string","\"git@github.com:[^ ]*\""],
["string.start","\""],
["string","git@github.com:[^ ]*"],
["string.end","\""],
["keyword.operator","`"],
["punctuation.operator",";"],
["text"," "],
@ -113,12 +115,16 @@
["keyword.operator","-"],
["identifier","e"],
["text"," "],
["string","\"s/^git@github\\.com://\""],
["string.start","\""],
["string","s/^git@github\\.com://"],
["string.end","\""],
["text"," "],
["keyword.operator","-"],
["identifier","e"],
["text"," "],
["string","\"s/\\.git$//\""]
["string.start","\""],
["string","s/\\.git$//"],
["string.end","\""]
],[
"start",
["text"," "],
@ -150,7 +156,9 @@
["keyword.operator","-"],
["identifier","o"],
["text"," "],
["string","\"https?://([^@]*@)?github.com/[^ ]*\\.git\""],
["string.start","\""],
["string","https?://([^@]*@)?github.com/[^ ]*\\.git"],
["string.end","\""],
["keyword.operator","`"],
["punctuation.operator",";"],
["text"," "],
@ -169,17 +177,23 @@
["keyword.operator","-"],
["identifier","e"],
["text"," "],
["string","\"s|^https?://||\""],
["string.start","\""],
["string","s|^https?://||"],
["string.end","\""],
["text"," "],
["keyword.operator","-"],
["identifier","e"],
["text"," "],
["string","\"s/^.*github\\.com\\///\""],
["string.start","\""],
["string","s/^.*github\\.com\\///"],
["string.end","\""],
["text"," "],
["keyword.operator","-"],
["identifier","e"],
["text"," "],
["string","\"s/\\.git$//\""]
["string.start","\""],
["string","s/\\.git$//"],
["string.end","\""]
],[
"start",
["text"," "],
@ -211,7 +225,9 @@
["keyword.operator","-"],
["identifier","o"],
["text"," "],
["string","\"git://github.com/[^ ]*\\.git\""],
["string.start","\""],
["string","git://github.com/[^ ]*\\.git"],
["string.end","\""],
["keyword.operator","`"],
["punctuation.operator",";"],
["text"," "],
@ -230,12 +246,16 @@
["keyword.operator","-"],
["identifier","e"],
["text"," "],
["string","\"s|^git://github.com/||\""],
["string.start","\""],
["string","s|^git://github.com/||"],
["string.end","\""],
["text"," "],
["keyword.operator","-"],
["identifier","e"],
["text"," "],
["string","\"s/\\.git$//\""]
["string.start","\""],
["string","s/\\.git$//"],
["string.end","\""]
],[
"start",
["text"," "],
@ -275,7 +295,9 @@
["text"," "],
["support.function.builtin","echo"],
["text"," "],
["string","\"Couldn't find a valid remote\""],
["string.start","\""],
["string","Couldn't find a valid remote"],
["string.end","\""],
["text"," "],
["keyword.operator",">"],
["support.function","&2"]
@ -344,7 +366,8 @@
["text"," "],
["support.function.builtin","echo"],
["text"," "],
["string","\"http://github.com/"],
["string.start","\""],
["string","http://github.com/"],
["variable","$repo"],
["string","/pull/new/"],
["variable","$"],
@ -356,7 +379,7 @@
["identifier","heads"],
["keyword.operator","/"],
["paren.rparen","}"],
["string","\""]
["string.end","\""]
],[
"start",
["keyword","else"]

Wyświetl plik

@ -77,9 +77,8 @@
],[
"start",
["text"," x="],
["keyword","\\left\\"],
["paren.keyword.operator","{"],
["text"," "],
["keyword","\\left"],
["text", "\\{ "],
["keyword","\\begin"],
["paren.keyword.operator","{"],
["nospell.text","array"],
@ -127,4 +126,4 @@
["paren.keyword.operator","{"],
["nospell.text","equation"],
["paren.keyword.operator","}"]
]]
]]

Wyświetl plik

@ -100,14 +100,18 @@
["string","'button'"],
["paren.rparen",")"]
],[
"no_regex",
"start",
["identifier","button"],
["punctuation.operator","."],
["identifier","innerText"],
["text"," "],
["keyword.operator","="],
["text"," "],
["string","\"Say Hello\""]
["keyword.operator","<"],
["storage.type.variable.ts","string"],
["keyword.operator",">"],
["string","\"Say Hello\""],
["punctuation.operator",";"]
],[
"start",
["storage.type","button"],

Wyświetl plik

@ -69,7 +69,7 @@ var c_cppHighlightRules = function() {
next : "comment"
}, {
token : "string", // character
regex : "'(?:" + escapeRe + "|.)'"
regex : "'(?:" + escapeRe + "|.)?'"
}, {
token : "string.start",
regex : '"',

Wyświetl plik

@ -52,8 +52,7 @@ define(function(require, exports, module) {
var illegal = (
"case|const|default|function|var|void|with|enum|export|implements|" +
"interface|let|package|private|protected|public|static|yield|" +
"__hasProp|slice|bind|indexOf"
"interface|let|package|private|protected|public|static|yield"
);
var supportClass = (

Wyświetl plik

@ -28,7 +28,7 @@ var CSharpHighlightRules = function() {
next : "comment"
}, {
token : "string", // character
regex : /'(?:.|\\(:?u[\da-fA-F]+|x[\da-fA-F]+|[tbrf'"n]))'/
regex : /'(?:.|\\(:?u[\da-fA-F]+|x[\da-fA-F]+|[tbrf'"n]))?'/
}, {
token : "string", start : '"', end : '"|$', next: [
{token: "constant.language.escape", regex: /\\(:?u[\da-fA-F]+|x[\da-fA-F]+|[tbrf'"n])/},

2
node_modules/ace/lib/ace/mode/ejs.js wygenerowano vendored
Wyświetl plik

@ -52,7 +52,7 @@ var EjsHighlightRules = function(start, end) {
});
}
this.embedRules(JavaScriptHighlightRules, "ejs-", [{
this.embedRules(new JavaScriptHighlightRules({jsx: false}).getRules(), "ejs-", [{
token : "markup.list.meta.tag",
regex : "-?" + end,
next : "pop"

Wyświetl plik

@ -45,7 +45,7 @@ var ForthHighlightRules = function() {
// regexps are ordered -> the first match is used
this.$rules = { start: [ { include: '#forth' } ],
'#comment':
'#comment':
[ { token: 'comment.line.double-dash.forth',
regex: '(?:^|\\s)--\\s.*$',
comment: 'line comments for iForth' },
@ -57,7 +57,7 @@ var ForthHighlightRules = function() {
comment: 'gForth line comment' },
{ token: 'comment.block.forth',
regex: '(?:^|\\s)\\(\\*(?=\\s|$)',
push:
push:
[ { token: 'comment.block.forth',
regex: '(?:^|\\s)\\*\\)(?=\\s|$)',
next: 'pop' },
@ -66,7 +66,7 @@ var ForthHighlightRules = function() {
{ token: 'comment.block.documentation.forth',
regex: '\\bDOC\\b',
caseInsensitive: true,
push:
push:
[ { token: 'comment.block.documentation.forth',
regex: '\\bENDDOC\\b',
caseInsensitive: true,
@ -76,7 +76,7 @@ var ForthHighlightRules = function() {
{ token: 'comment.line.parentheses.forth',
regex: '(?:^|\\s)\\.?\\( [^)]*\\)',
comment: 'ANSI line comment' } ],
'#constant':
'#constant':
[ { token: 'constant.language.forth',
regex: '(?:^|\\s)(?:TRUE|FALSE|BL|PI|CELL|C/L|R/O|W/O|R/W)(?=\\s|$)',
caseInsensitive: true},
@ -84,7 +84,7 @@ var ForthHighlightRules = function() {
regex: '(?:^|\\s)[$#%]?[-+]?[0-9]+(?:\\.[0-9]*e-?[0-9]+|\\.?[0-9a-fA-F]*)(?=\\s|$)'},
{ token: 'constant.character.forth',
regex: '(?:^|\\s)(?:[&^]\\S|(?:"|\')\\S(?:"|\'))(?=\\s|$)'}],
'#forth':
'#forth':
[ { include: '#constant' },
{ include: '#comment' },
{ include: '#string' },
@ -92,22 +92,22 @@ var ForthHighlightRules = function() {
{ include: '#variable' },
{ include: '#storage' },
{ include: '#word-def' } ],
'#storage':
'#storage':
[ { token: 'storage.type.forth',
regex: '(?:^|\\s)(?:2CONSTANT|2VARIABLE|ALIAS|CONSTANT|CREATE-INTERPRET/COMPILE[:]?|CREATE|DEFER|FCONSTANT|FIELD|FVARIABLE|USER|VALUE|VARIABLE|VOCABULARY)(?=\\s|$)',
caseInsensitive: true}],
'#string':
'#string':
[ { token: 'string.quoted.double.forth',
regex: '(ABORT" |BREAK" |\\." |C" |0"|S\\\\?" )([^"]+")',
caseInsensitive: true},
{ token: 'string.unquoted.forth',
regex: '(?:INCLUDE|NEEDS|REQUIRE|USE)[ ]\\S+(?=\\s|$)',
caseInsensitive: true}],
'#variable':
'#variable':
[ { token: 'variable.language.forth',
regex: '\\b(?:I|J)\\b',
caseInsensitive: true } ],
'#word':
'#word':
[ { token: 'keyword.control.immediate.forth',
regex: '(?:^|\\s)\\[(?:\\?DO|\\+LOOP|AGAIN|BEGIN|DEFINED|DO|ELSE|ENDIF|FOR|IF|IFDEF|IFUNDEF|LOOP|NEXT|REPEAT|THEN|UNTIL|WHILE)\\](?=\\s|$)',
caseInsensitive: true},
@ -126,15 +126,15 @@ var ForthHighlightRules = function() {
{ token: 'keyword.other.warning.forth',
regex: '(?:^|\\s)(?:~~|BREAK:|BREAK"|DBG)(?=\\s|$)',
caseInsensitive: true}],
'#word-def':
[ { token:
'#word-def':
[ { token:
[ 'keyword.other.compile-only.forth',
'keyword.other.compile-only.forth',
'meta.block.forth',
'entity.name.function.forth' ],
regex: '(:NONAME)|(^:|\\s:)(\\s)(\\S+)(?=\\s|$)',
caseInsensitive: true,
push:
push:
[ { token: 'keyword.other.compile-only.forth',
regex: ';(?:CODE)?',
caseInsensitive: true,
@ -150,7 +150,7 @@ var ForthHighlightRules = function() {
this.normalizeRules();
};
ForthHighlightRules.metaData = { fileTypes: [ 'frt', 'fs', 'ldr' ],
ForthHighlightRules.metaData = { fileTypes: [ 'frt', 'fs', 'ldr', 'fth', '4th' ],
foldingStartMarker: '/\\*\\*|\\{\\s*$',
foldingStopMarker: '\\*\\*/|^\\s*\\}',
keyEquivalent: '^~F',

60
node_modules/ace/lib/ace/mode/haskell_cabal.js wygenerowano vendored 100644
Wyświetl plik

@ -0,0 +1,60 @@
/* ***** BEGIN LICENSE BLOCK *****
* Distributed under the BSD license:
*
* Copyright (c) 2012, Ajax.org B.V.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of Ajax.org B.V. nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*
* Contributor(s):
*
*
*
* ***** END LICENSE BLOCK ***** */
/**
* Haskell Cabal files mode (https://www.haskell.org/cabal/users-guide/developing-packages.html)
**/
define(function(require, exports, module) {
"use strict";
var oop = require("../lib/oop");
var TextMode = require("./text").Mode;
var CabalHighlightRules = require("./haskell_cabal_highlight_rules").CabalHighlightRules;
var FoldMode = require("./folding/haskell_cabal").FoldMode;
var Mode = function() {
this.HighlightRules = CabalHighlightRules;
this.foldingRules = new FoldMode();
};
oop.inherits(Mode, TextMode);
(function() {
this.lineCommentStart = "--";
this.blockComment = null;
this.$id = "ace/mode/haskell_cabal";
}).call(Mode.prototype);
exports.Mode = Mode;
});

Wyświetl plik

@ -0,0 +1,68 @@
/* ***** BEGIN LICENSE BLOCK *****
* Distributed under the BSD license:
*
* Copyright (c) 2010, Ajax.org B.V.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of Ajax.org B.V. nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* ***** END LICENSE BLOCK ***** */
/**
* Haskell Cabal files highlighter (https://www.haskell.org/cabal/users-guide/developing-packages.html)
**/
define(function(require, exports, module) {
"use strict";
var oop = require("../lib/oop");
var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
var CabalHighlightRules = function() {
// regexp must not have capturing parentheses. Use (?:) instead.
// regexps are ordered -> the first match is used
this.$rules = {
"start" : [
{
token : "comment",
regex : "^\\s*--.*$"
}, {
token: ["keyword"],
regex: /^(\s*\w.*?)(\:(?:\s+|$))/
}, {
token : "constant.numeric", // float
regex : /[\d_]+(?:(?:[\.\d_]*)?)/
}, {
token : "constant.language.boolean",
regex : "(?:true|false|TRUE|FALSE|True|False|yes|no)\\b"
}, {
token : "markup.heading",
regex : /^(\w.*)$/
}
]};
};
oop.inherits(CabalHighlightRules, TextHighlightRules);
exports.CabalHighlightRules = CabalHighlightRules;
});

Wyświetl plik

@ -44,8 +44,8 @@ var HaskellHighlightRules = function() {
// regexp must not have capturing parentheses. Use (?:) instead.
// regexps are ordered -> the first match is used
this.$rules = { start:
[ { token:
this.$rules = { start:
[ { token:
[ 'punctuation.definition.entity.haskell',
'keyword.operator.function.infix.haskell',
'punctuation.definition.entity.haskell' ],
@ -56,7 +56,7 @@ var HaskellHighlightRules = function() {
regex: '\\[\\]' },
{ token: 'keyword.other.haskell',
regex: '\\bmodule\\b',
push:
push:
[ { token: 'keyword.other.haskell', regex: '\\bwhere\\b', next: 'pop' },
{ include: '#module_name' },
{ include: '#module_exports' },
@ -64,7 +64,7 @@ var HaskellHighlightRules = function() {
{ defaultToken: 'meta.declaration.module.haskell' } ] },
{ token: 'keyword.other.haskell',
regex: '\\bclass\\b',
push:
push:
[ { token: 'keyword.other.haskell',
regex: '\\bwhere\\b',
next: 'pop' },
@ -77,7 +77,7 @@ var HaskellHighlightRules = function() {
{ defaultToken: 'meta.declaration.class.haskell' } ] },
{ token: 'keyword.other.haskell',
regex: '\\binstance\\b',
push:
push:
[ { token: 'keyword.other.haskell',
regex: '\\bwhere\\b|$',
next: 'pop' },
@ -85,15 +85,15 @@ var HaskellHighlightRules = function() {
{ defaultToken: 'meta.declaration.instance.haskell' } ] },
{ token: 'keyword.other.haskell',
regex: 'import',
push:
[ { token: 'meta.import.haskell', regex: '$|;', next: 'pop' },
push:
[ { token: 'meta.import.haskell', regex: '$|;|^', next: 'pop' },
{ token: 'keyword.other.haskell', regex: 'qualified|as|hiding' },
{ include: '#module_name' },
{ include: '#module_exports' },
{ defaultToken: 'meta.import.haskell' } ] },
{ token: [ 'keyword.other.haskell', 'meta.deriving.haskell' ],
regex: '(deriving)(\\s*\\()',
push:
push:
[ { token: 'meta.deriving.haskell', regex: '\\)', next: 'pop' },
{ token: 'entity.other.inherited-class.haskell',
regex: '\\b[A-Z][a-zA-Z_\']*' },
@ -108,7 +108,7 @@ var HaskellHighlightRules = function() {
comment: 'Floats are always decimal' },
{ token: 'constant.numeric.haskell',
regex: '\\b(?:[0-9]+|0(?:[xX][0-9a-fA-F]+|[oO][0-7]+))\\b' },
{ token:
{ token:
[ 'meta.preprocessor.c',
'punctuation.definition.preprocessor.c',
'meta.preprocessor.c' ],
@ -117,7 +117,7 @@ var HaskellHighlightRules = function() {
{ include: '#pragma' },
{ token: 'punctuation.definition.string.begin.haskell',
regex: '"',
push:
push:
[ { token: 'punctuation.definition.string.end.haskell',
regex: '"',
next: 'pop' },
@ -128,7 +128,7 @@ var HaskellHighlightRules = function() {
{ token: 'constant.character.escape.control.haskell',
regex: '\\^[A-Z@\\[\\]\\\\\\^_]' },
{ defaultToken: 'string.quoted.double.haskell' } ] },
{ token:
{ token:
[ 'punctuation.definition.string.begin.haskell',
'string.quoted.single.haskell',
'constant.character.escape.haskell',
@ -137,13 +137,13 @@ var HaskellHighlightRules = function() {
'constant.character.escape.control.haskell',
'punctuation.definition.string.end.haskell' ],
regex: '(\')(?:([\\ -\\[\\]-~])|(\\\\(?:NUL|SOH|STX|ETX|EOT|ENQ|ACK|BEL|BS|HT|LF|VT|FF|CR|SO|SI|DLE|DC1|DC2|DC3|DC4|NAK|SYN|ETB|CAN|EM|SUB|ESC|FS|GS|RS|US|SP|DEL|[abfnrtv\\\\\\"\'\\&]))|(\\\\o[0-7]+)|(\\\\x[0-9A-Fa-f]+)|(\\^[A-Z@\\[\\]\\\\\\^_]))(\')' },
{ token:
{ token:
[ 'meta.function.type-declaration.haskell',
'entity.name.function.haskell',
'meta.function.type-declaration.haskell',
'keyword.other.double-colon.haskell' ],
regex: '^(\\s*)([a-z_][a-zA-Z0-9_\']*|\\([|!%$+\\-.,=</>]+\\))(\\s*)(::)',
push:
push:
[ { token: 'meta.function.type-declaration.haskell',
regex: '$',
next: 'pop' },
@ -160,32 +160,32 @@ var HaskellHighlightRules = function() {
regex: '[|!%$?~+:\\-.=</>\\\\]+',
comment: 'In case this regex seems overly general, note that Haskell permits the definition of new operators which can be nearly any string of punctuation characters, such as $%^&*.' },
{ token: 'punctuation.separator.comma.haskell', regex: ',' } ],
'#block_comment':
'#block_comment':
[ { token: 'punctuation.definition.comment.haskell',
regex: '\\{-(?!#)',
push:
push:
[ { include: '#block_comment' },
{ token: 'punctuation.definition.comment.haskell',
regex: '-\\}',
next: 'pop' },
{ defaultToken: 'comment.block.haskell' } ] } ],
'#comments':
'#comments':
[ { token: 'punctuation.definition.comment.haskell',
regex: '--.*',
push_:
push_:
[ { token: 'comment.line.double-dash.haskell',
regex: '$',
next: 'pop' },
{ defaultToken: 'comment.line.double-dash.haskell' } ] },
{ include: '#block_comment' } ],
'#infix_op':
'#infix_op':
[ { token: 'entity.name.function.infix.haskell',
regex: '\\([|!%$+:\\-.=</>]+\\)|\\(,+\\)' } ],
'#module_exports':
'#module_exports':
[ { token: 'meta.declaration.exports.haskell',
regex: '\\(',
push:
[ { token: 'meta.declaration.exports.haskell',
push:
[ { token: 'meta.declaration.exports.haskell.end',
regex: '\\)',
next: 'pop' },
{ token: 'entity.name.function.haskell',
@ -196,22 +196,22 @@ var HaskellHighlightRules = function() {
{ token: 'meta.other.unknown.haskell',
regex: '\\(.*?\\)',
comment: 'So named because I don\'t know what to call this.' },
{ defaultToken: 'meta.declaration.exports.haskell' } ] } ],
'#module_name':
{ defaultToken: 'meta.declaration.exports.haskell.end' } ] } ],
'#module_name':
[ { token: 'support.other.module.haskell',
regex: '[A-Z][A-Za-z._\']*' } ],
'#pragma':
'#pragma':
[ { token: 'meta.preprocessor.haskell',
regex: '\\{-#',
push:
push:
[ { token: 'meta.preprocessor.haskell',
regex: '#-\\}',
next: 'pop' },
{ token: 'keyword.other.preprocessor.haskell',
regex: '\\b(?:LANGUAGE|UNPACK|INLINE)\\b' },
{ defaultToken: 'meta.preprocessor.haskell' } ] } ],
'#type_signature':
[ { token:
'#type_signature':
[ { token:
[ 'meta.class-constraint.haskell',
'entity.other.inherited-class.haskell',
'meta.class-constraint.haskell',
@ -230,7 +230,7 @@ var HaskellHighlightRules = function() {
regex: '\\b[A-Z][a-zA-Z0-9_\']*\\b' },
{ token: 'support.constant.unit.haskell', regex: '\\(\\)' },
{ include: '#comments' } ] }
this.normalizeRules();
};
@ -243,4 +243,4 @@ HaskellHighlightRules.metaData = { fileTypes: [ 'hs' ],
oop.inherits(HaskellHighlightRules, TextHighlightRules);
exports.HaskellHighlightRules = HaskellHighlightRules;
});
});

Wyświetl plik

@ -506,11 +506,26 @@ var PhpLangHighlightRules = function() {
'mysql_field_name|mysql_field_seek|mysql_field_table|mysql_field_type|mysql_free_result|mysql_get_client_info|mysql_get_host_info|' +
'mysql_get_proto_info|mysql_get_server_info|mysql_info|mysql_insert_id|mysql_list_dbs|mysql_list_fields|mysql_list_processes|' +
'mysql_list_tables|mysql_num_fields|mysql_num_rows|mysql_pconnect|mysql_ping|mysql_query|mysql_real_escape_string|mysql_result|' +
'mysql_select_db|mysql_set_charset|mysql_stat|mysql_tablename|mysql_thread_id|mysql_unbuffered_query|mysqli|mysqli_bind_param|' +
'mysqli_bind_result|mysqli_client_encoding|mysqli_connect|mysqli_disable_reads_from_master|mysqli_disable_rpl_parse|mysqli_driver|' +
'mysqli_enable_reads_from_master|mysqli_enable_rpl_parse|mysqli_escape_string|mysqli_execute|mysqli_fetch|mysqli_get_metadata|' +
'mysqli_master_query|mysqli_param_count|mysqli_report|mysqli_result|mysqli_rpl_parse_enabled|mysqli_rpl_probe|mysqli_rpl_query_type|' +
'mysqli_send_long_data|mysqli_send_query|mysqli_set_opt|mysqli_slave_query|mysqli_stmt|mysqli_warning|mysqlnd_ms_get_stats|' +
'mysql_select_db|mysql_set_charset|mysql_stat|mysql_tablename|mysql_thread_id|mysql_unbuffered_query|mysqli|mysqli_affected_rows|' +
'mysqli_autocommit|mysqli_bind_param|mysqli_bind_result|mysqli_cache_stats|mysqli_change_user|mysqli_character_set_name|' +
'mysqli_client_encoding|mysqli_close|mysqli_commit|mysqli_connect|mysqli_connect_errno|mysqli_connect_error|mysqli_data_seek|' +
'mysqli_debug|mysqli_disable_reads_from_master|mysqli_disable_rpl_parse|mysqli_driver|mysqli_dump_debug_info|mysqli_embedded_server_end|' +
'mysqli_embedded_server_start|mysqli_enable_reads_from_master|mysqli_enable_rpl_parse|mysqli_errno|mysqli_error|mysqli_escape_string|' +
'mysqli_execute|mysqli_fetch|mysqli_fetch_all|mysqli_fetch_array|mysqli_fetch_assoc|mysqli_fetch_field|mysqli_fetch_field_direct|' +
'mysqli_fetch_fields|mysqli_fetch_lengths|mysqli_fetch_object|mysqli_fetch_row|mysqli_field_count|mysqli_field_seek|mysqli_field_tell|' +
'mysqli_free_result|mysqli_get_charset|mysqli_get_client_info|mysqli_get_client_stats|mysqli_get_client_version|mysqli_get_connection_stats|' +
'mysqli_get_host_info|mysqli_get_metadata|mysqli_get_proto_info|mysqli_get_server_info|mysqli_get_server_version|mysqli_get_warnings|' +
'mysqli_info|mysqli_init|mysqli_insert_id|mysqli_kill|mysqli_link_construct|mysqli_master_query|mysqli_more_results|mysqli_multi_query|' +
'mysqli_next_result|mysqli_num_fields|mysqli_num_rows|mysqli_options|mysqli_param_count|mysqli_ping|mysqli_poll|mysqli_prepare|' +
'mysqli_query|mysqli_real_connect|mysqli_real_escape_string|mysqli_real_query|mysqli_reap_async_query|mysqli_refresh|mysqli_report|' +
'mysqli_result|mysqli_rollback|mysqli_rpl_parse_enabled|mysqli_rpl_probe|mysqli_rpl_query_type|mysqli_select_db|mysqli_send_long_data|' +
'mysqli_send_query|mysqli_set_charset|mysqli_set_local_infile_default|mysqli_set_local_infile_handler|mysqli_set_opt|mysqli_slave_query|' +
'mysqli_sqlstate|mysqli_ssl_set|mysqli_stat|mysqli_stmt|mysqli_stmt_affected_rows|mysqli_stmt_attr_get|mysqli_stmt_attr_set|' +
'mysqli_stmt_bind_param|mysqli_stmt_bind_result|mysqli_stmt_close|mysqli_stmt_data_seek|mysqli_stmt_errno|mysqli_stmt_error|' +
'mysqli_stmt_execute|mysqli_stmt_fetch|mysqli_stmt_field_count|mysqli_stmt_free_result|mysqli_stmt_get_result|mysqli_stmt_get_warnings|' +
'mysqli_stmt_init|mysqli_stmt_insert_id|mysqli_stmt_next_result|mysqli_stmt_num_rows|mysqli_stmt_param_count|mysqli_stmt_prepare|' +
'mysqli_stmt_reset|mysqli_stmt_result_metadata|mysqli_stmt_send_long_data|mysqli_stmt_sqlstate|mysqli_stmt_store_result|mysqli_store_result|' +
'mysqli_thread_id|mysqli_thread_safe|mysqli_use_result|mysqli_warning|mysqli_warning_count|mysqlnd_ms_get_stats|' +
'mysqlnd_ms_query_is_select|mysqlnd_ms_set_user_pick_server|mysqlnd_qc_change_handler|mysqlnd_qc_clear_cache|mysqlnd_qc_get_cache_info|' +
'mysqlnd_qc_get_core_stats|mysqlnd_qc_get_handler|mysqlnd_qc_get_query_trace_log|mysqlnd_qc_set_user_handlers|natcasesort|natsort|' +
'ncurses_addch|ncurses_addchnstr|ncurses_addchstr|ncurses_addnstr|ncurses_addstr|ncurses_assume_default_colors|ncurses_attroff|' +

Wyświetl plik

@ -64,7 +64,7 @@ var TexHighlightRules = function(textClass) {
next : "nospell"
}, {
token : "keyword", // command
regex : "\\\\(?:[a-zA-z0-9]+|[^a-zA-z0-9])"
regex : "\\\\(?:[a-zA-Z0-9]+|[^a-zA-Z0-9])"
}, {
// Obviously these are neither keywords nor operators, but
// labelling them as such was the easiest way to get them
@ -98,7 +98,7 @@ var TexHighlightRules = function(textClass) {
regex : "\\\\(?:documentclass|usepackage|newcounter|setcounter|addtocounter|value|arabic|stepcounter|newenvironment|renewenvironment|ref|vref|eqref|pageref|label|cite[a-zA-Z]*|tag|begin|end|bibitem)\\b"
}, {
token : "keyword", // command
regex : "\\\\(?:[a-zA-z0-9]+|[^a-zA-z0-9])",
regex : "\\\\(?:[a-zA-Z0-9]+|[^a-zA-Z0-9])",
next : "start"
}, {
token : "paren.keyword.operator",

11
node_modules/ace/lib/ace/scrollbar.js wygenerowano vendored
Wyświetl plik

@ -35,6 +35,9 @@ var oop = require("./lib/oop");
var dom = require("./lib/dom");
var event = require("./lib/event");
var EventEmitter = require("./lib/event_emitter").EventEmitter;
// on ie maximal element height is smaller than what we get from 4-5K line document
// so scrollbar doesn't work, as a workaround we do not set height higher than MAX_SCROLL_H
// and rescale scrolltop
var MAX_SCROLL_H = 0x8000;
/**
@ -90,6 +93,7 @@ var ScrollBar = function(parent) {
var VScrollBar = function(parent, renderer) {
ScrollBar.call(this, parent);
this.scrollTop = 0;
this.scrollHeight = 0;
// in OSX lion the scrollbars appear to have no width. In this case resize the
// element to show the scrollbar but still pretend that the scrollbar has a width
@ -116,7 +120,11 @@ oop.inherits(VScrollBar, ScrollBar);
**/
this.onScroll = function() {
if (!this.skipEvent) {
this.scrollTop = this.element.scrollTop / this.coeff;
this.scrollTop = this.element.scrollTop;
if (this.coeff != 1) {
var h = this.element.clientHeight / this.scrollHeight;
this.scrollTop = this.scrollTop * (1 - h) / (this.coeff - h);
}
this._emit("scroll", {data: this.scrollTop});
}
this.skipEvent = false;
@ -149,6 +157,7 @@ oop.inherits(VScrollBar, ScrollBar);
* @param {Number} height The new scroll height
**/
this.setScrollHeight = function(height) {
this.scrollHeight = height;
if (height > MAX_SCROLL_H) {
this.coeff = MAX_SCROLL_H / height;
height = MAX_SCROLL_H;

8
node_modules/ace/lib/ace/snippets.js wygenerowano vendored
Wyświetl plik

@ -277,6 +277,7 @@ var SnippetManager = function() {
if (cursor.column < indentString.length)
indentString = indentString.slice(0, cursor.column);
snippetText = snippetText.replace(/\r/g, "");
var tokens = this.tokenizeTmSnippet(snippetText);
tokens = this.resolveVariables(tokens, editor);
// indent
@ -362,9 +363,10 @@ var SnippetManager = function() {
var text = "";
tokens.forEach(function(t) {
if (typeof t === "string") {
if (t[0] === "\n"){
column = t.length - 1;
row ++;
var lines = t.split("\n");
if (lines.length > 1){
column = lines[lines.length - 1].length;
row += lines.length - 1;
} else
column += t.length;
text += t;

7
node_modules/ace/lib/ace/snippets/rst.js wygenerowano vendored 100644
Wyświetl plik

@ -0,0 +1,7 @@
define(function(require, exports, module) {
"use strict";
exports.snippetText = require("../requirejs/text!./.snippets");
exports.scope = "";
});

Wyświetl plik

@ -97,18 +97,25 @@ module.exports = {
assert.equal(tokens[1].flag, "g");
},
"test: expand snippet with nested tabstops": function() {
var content = "-${1}-${1:1}--${2:2 ${3} 2}-${3:3 $1 3}-${4:4 $2 4}";
var content = "-${1}-${1:t\n1}--${2:2 ${3} 2}-${3:3 $1 3}-${4:4 $2 4}";
this.editor.setValue("");
snippetManager.insertSnippet(this.editor, content);
assert.equal(this.editor.getValue(), "-1-1--2 3 1 3 2-3 1 3-4 2 3 1 3 2 4");
assert.equal(this.editor.getValue(), [
"-t",
"1-t",
"1--2 3 t",
"1 3 2-3 t",
"1 3-4 2 3 t",
"1 3 2 4"
].join("\n"));
assert.equal(this.editor.getSelectedText(), "1\n1\n1\n1\n1");
assert.equal(this.editor.getSelectedText(), "t\n1\nt\n1\nt\n1\nt\n1\nt\n1");
this.editor.tabstopManager.tabNext();
assert.equal(this.editor.getSelectedText(), "2 3 1 3 2\n2 3 1 3 2");
assert.equal(this.editor.getSelectedText(), "2 3 t\n1 3 2\n2 3 t\n1 3 2");
this.editor.tabstopManager.tabNext();
assert.equal(this.editor.getSelectedText(), "3 1 3\n3 1 3\n3 1 3");
assert.equal(this.editor.getSelectedText(), "3 t\n1 3\n3 t\n1 3\n3 t\n1 3");
this.editor.tabstopManager.tabNext();
assert.equal(this.editor.getSelectedText(), "4 2 3 1 3 2 4");
assert.equal(this.editor.getSelectedText(), "4 2 3 t\n1 3 2 4");
this.editor.tabstopManager.tabNext();
assert.equal(this.editor.getSelectedText(), "");

18
node_modules/ace/lib/ace/test/mockdom.js wygenerowano vendored
Wyświetl plik

@ -1,14 +1,10 @@
"use strict";
var dom = require('node-jsdom/lib/jsdom/living');
var browser = require('node-jsdom/lib/jsdom/browser/index').browserAugmentation(dom);
var doc = new browser.HTMLDocument({parsingMode: 'html'});
doc.write("<html><head></head><body></body></html>");
browser.document = doc;
browser.window = doc.defaultView;
var jsdom = require('jsdom/').jsdom;
var doc = jsdom("<html><head></head><body></body></html>")
global.document = browser.document;
global.window = browser.window;
global.self = browser.self;
global.navigator = browser.navigator;
global.location = browser.location;
global.document = doc;
global.window = doc.defaultView;
global.self = doc.self;
global.navigator = doc.navigator;
global.location = doc.location;

Wyświetl plik

@ -393,8 +393,6 @@ var loadScriptWithTag = function(path, id, callback) {
if (path.lastIndexOf(require.MODULE_LOAD_URL, 0) == 0 && path[0] != "/")
s.crossOrigin = true;
head.appendChild(s);
s.onload = s.onreadystatechange = function(_, isAbort) {
if (isAbort || !s.readyState || s.readyState == "loaded" || s.readyState == "complete") {
s = s.onload = s.onreadystatechange = null;
@ -409,6 +407,7 @@ var loadScriptWithTag = function(path, id, callback) {
path: path
});
};
head.appendChild(s);
};
function loadText(path, cb) {
@ -468,6 +467,9 @@ var loadCached = function(path, cb) {
}
});
}
if (!ideCache && !ideCachePromiss) {
checkCache();
}
if (ideCachePromiss) {
return ideCachePromiss.then(function(i) {
if (i) ideCache = i;
@ -494,7 +496,10 @@ var ideCache;
var ideCachePromiss;
function checkCache() {
var baseUrl;
ideCachePromiss = config.useCache && window.caches.open("ide").then(function(ideCache_) {
ideCachePromiss = config.useCache && window.caches.open("ide").catch(function(e) {
console.error(e);
config.useCache = ideCachePromiss = ideCache = null;
}).then(function(ideCache_) {
ideCache = ideCache_;
return ideCache.keys();
}).then(function(keys) {
@ -557,7 +562,7 @@ require.clearCache = function(callback) {
callback && callback(e);
});
});
}
};
function post(path, val, progress, cb) {
var xhr = new window.XMLHttpRequest();

2
node_modules/c9/docker-helpers_test.js wygenerowano vendored
Wyświetl plik

@ -64,6 +64,8 @@ describe("docker-helpers", function() {
assert.equal(dockerHelpers.getProjectIdFromContainerName("container-stefko-demo-project-884917"), "884917");
assert.equal(dockerHelpers.getProjectIdFromContainerName("container-scollins-booking_admin-1667108-yORDDrjnsOiiLveG"), "1667108");
assert.equal(dockerHelpers.getProjectIdFromContainerName("jakrawczt-test-3-jkr-1633955"), "1633955");
assert.equal(dockerHelpers.getProjectIdFromContainerName("jakrawczt-test-489552-1633956"), "1633956");
assert.equal(dockerHelpers.getProjectIdFromContainerName("/container-jan1365-ide50-2380083-XoEYNkUIDRuLqvBZ"), "2380083");
assert.equal(dockerHelpers.getProjectIdFromContainerName("thn85-p18-1016460"), "1016460");
assert.equal(dockerHelpers.getProjectIdFromContainerName("thn85-proj-18239823-1016490"), "1016490");
assert.equal(dockerHelpers.getProjectIdFromContainerName("artawil-etutor_11plus-wp-1422098"), "1422098");

19
node_modules/c9/passcrypt.js wygenerowano vendored
Wyświetl plik

@ -6,15 +6,21 @@
var hashing = require('./hashing');
var bcrypt;
try {
bcrypt = require('bcrypt');
} catch (e) {
console.error("Failed to load brcrypt - binary version mismatch?", e.stack);
process.exit(1);
}
var SALT_LENGTH = 8;
function loadBcrypt() {
if (bcrypt) return;
try {
bcrypt = require('bcrypt');
} catch (e) {
console.error("Failed to load bcrypt - binary version mismatch?", e.stack);
process.exit(1);
}
}
exports.encrypt = function(password, callback) {
loadBcrypt();
var passwordHashed = hashing.md5(password);
bcrypt.hash(passwordHashed, SALT_LENGTH, function(err, passwordEncrypted) {
if (err) return callback(err);
@ -23,6 +29,7 @@ exports.encrypt = function(password, callback) {
};
exports.compare = function(password, encrypted, callback) {
loadBcrypt();
var passwordHashed = hashing.md5(password);
if (passwordHashed == encrypted) { // Some passwords may still only be hashed, not bcrypted, so see if that worked first.
return callback(null, true);

Wyświetl plik

@ -30,15 +30,6 @@ module.exports = function startup(options, imports, register) {
var sessionRoutes = connectModule();
connect.useSession(sessionRoutes);
sessionRoutes.use(
function(req, res, next) {
if (/^\/geckolala\//.test(req.url))
return next(new error.TooManyRequests("Rate limit exceeded"));
next();
}
);
sessionRoutes.use(Session(sessionOptions, cookie));
register(null, {

2
node_modules/kaefer/lib/version.js wygenerowano vendored
Wyświetl plik

@ -2,6 +2,6 @@ define(function(require, exports, module) {
// on each backwards incompatible protocol change the version number must be
// increased
exports.protocol = 12;
exports.protocol = 13;
});

Wyświetl plik

@ -17,7 +17,7 @@ module.exports = function setup(mount, vfs, mountOptions) {
}
if (code) res.statusCode = code;
else if (typeof err.code == "number") res.statusCode = err.code;
else if (typeof err.code == "number" && isValidStatusCode(err.code)) res.statusCode = err.code;
else if (err.code === "EBADREQUEST") res.statusCode = 400;
else if (err.code === "EACCES") res.statusCode = 403;
else if (err.code === "ENOENT") res.statusCode = 404;
@ -29,6 +29,10 @@ module.exports = function setup(mount, vfs, mountOptions) {
res.setHeader("Content-Length", Buffer.byteLength(message));
res.end(message);
};
function isValidStatusCode(statusCode) {
return statusCode >= 100 && statusCode <= 999;
}
// Returns a json stream that wraps input object stream
function jsonEncoder(input, path) {

40
node_modules/vfs-local/localfs.js wygenerowano vendored
Wyświetl plik

@ -128,7 +128,7 @@ module.exports = function setup(fsOptions) {
_execFile(TMUX, ["-V"], function(err, stdout) {
if (err) stdout = "tmux 1.9";
noTmux = err && err.code === "ENOENT";
TMUXNAME = "cloud9" + parseFloat(stdout.replace(/tmux /, ""), 10);
TMUXNAME = "cloud9" + parseFloat(stdout.replace(/tmux([-\d.]*) /, ""), 10);
});
if (fsOptions.hasOwnProperty('defaultEnv')) {
@ -379,6 +379,7 @@ module.exports = function setup(fsOptions) {
} else {
entry.size = stat.size;
entry.mtime = stat.mtime.valueOf();
entry.ctime = stat.ctime.valueOf();
if (stat.isDirectory()) {
entry.mime = "inode/directory";
@ -429,8 +430,17 @@ module.exports = function setup(fsOptions) {
var meta = {};
resolvePath(path, options, function (err, realpath) {
if (err) return callback(err);
fn(realpath, function (err) {
if (err) return callback(err);
fn(realpath, function done(err) {
if (err) {
if (err.code == "ENOENT") {
return fs.exists(realpath, function(exists) {
if (exists) err.code = "EACCES";
callback(err);
});
} else {
return callback(err);
}
}
// Remove metadata
resolvePath(WSMETAPATH + path, options, function (err, realpath) {
@ -1003,7 +1013,17 @@ module.exports = function setup(fsOptions) {
function rmdir(path, options, callback) {
if (options.recursive) {
remove(path, function(path, callback) {
execFile("rm", {args: ["-rf", path]}, callback);
spawn("rm", {args: ["-rf", path], stdio: 'ignore'}, function(err, child) {
if (err) return callback(err);
child.process.on("close", function(code) {
if (code) {
var err = new Error("Permission denied.");
err.code = "EACCES";
return callback(err);
}
callback();
});
});
}, options, callback);
}
else {
@ -1926,10 +1946,18 @@ module.exports = function setup(fsOptions) {
function run(err){
if (err) return callback(err);
_setDefaultEnv(options);
delete options.env.TMUX;
// HACK: workaround for tmux 2.2 bug:
// tmux passes PATH to new sessions breaking rvm
var sep = isWin ? ";" : ":";
options.env.PATH = options.env.PATH.split(sep).filter(function(p) {
return !/\/rvm\//.test(p);
}).join(sep);
// ENDHACK
if (options.detach && options.output) {
_setDefaultEnv(options);
delete options.env.TMUX;
return _execFile(TMUX, args, {
args: args,

Wyświetl plik

@ -1,7 +1,7 @@
{
"name": "c9",
"description": "New Cloud9 Client",
"version": "3.1.2758",
"version": "3.1.2968",
"author": "Ajax.org B.V. <info@ajax.org>",
"private": true,
"main": "bin/c9",
@ -26,18 +26,18 @@
"mkdirp": "~0.3.5",
"msgpack-js": "~0.1.1",
"msgpack-js-browser": "~0.1.4",
"nak": "git://github.com/cloud9ide/nak.git#6deef931594",
"nak": "https://github.com/cloud9ide/nak.git#6deef931594",
"netutil": "~0.0.2",
"optimist": "~0.6.0",
"qs": "0.6.6",
"rusha": "^0.8.3",
"send": "~0.1.4",
"simple-mime": "~0.0.8",
"tern": "git://github.com/cloud9ide/tern.git#39015d544d4c00c7899fea4c95c2e5bc2720e68e",
"tern_from_ts": "git://github.com/cloud9ide/tern_from_ts.git#84d51dcb9b16b126a206789d4d4237cde2801fe4",
"tern": "https://github.com/cloud9ide/tern.git#39015d544d4c00c7899fea4c95c2e5bc2720e68e",
"tern_from_ts": "https://github.com/cloud9ide/tern_from_ts.git#84d51dcb9b16b126a206789d4d4237cde2801fe4",
"through": "2.2.0",
"tmp": "~0.0.20",
"uglify-js": "^2.6.2",
"uglify-js": "~2.6.2",
"ws": "0.4.31",
"read": "~1.0.5",
"form-data": "~0.2.0",
@ -58,7 +58,7 @@
"c9"
],
"c9plugins": {
"c9.ide.language": "#0e86345d39",
"c9.ide.language": "#0426ee345b",
"c9.ide.language.core": "#bfb5dd2acc",
"c9.ide.language.css": "#46ad561506",
"c9.ide.language.generic": "#b47cbe58f9",
@ -71,12 +71,12 @@
"c9.ide.language.javascript.infer": "#b9c2e4bdb8",
"c9.ide.language.jsonalyzer": "#a0549e14ff",
"c9.ide.language.codeintel": "#4e0a272229",
"c9.ide.collab": "#e015881720",
"c9.ide.collab": "#d149eae786",
"c9.ide.local": "#9169fec157",
"c9.ide.find": "#a2dfc3e306",
"c9.ide.find.infiles": "#488db22ee1",
"c9.ide.find.replace": "#47a84af707",
"c9.ide.run.debug": "#08249419c5",
"c9.ide.find": "#e632ecf4be",
"c9.ide.find.infiles": "#ad9ff74638",
"c9.ide.find.replace": "#8468067976",
"c9.ide.run.debug": "#651451a7c2",
"c9.automate": "#47e2c429c9",
"c9.ide.ace.emmet": "#6dc4585e02",
"c9.ide.ace.gotoline": "#d33220b1e0",
@ -93,8 +93,8 @@
"c9.ide.format": "#f99082ff4c",
"c9.ide.help.support": "#fbe8eb5c36",
"c9.ide.imgeditor": "#612e75ef4f",
"c9.ide.immediate": "#b279c69c73",
"c9.ide.installer": "#b2e4ba0a92",
"c9.ide.immediate": "#0b0ee744f9",
"c9.ide.installer": "#2921efaf6d",
"c9.ide.language.python": "#9fba572b1a",
"c9.ide.language.go": "#6ce1c7a7ef",
"c9.ide.navigate": "#5d5707058c",
@ -108,7 +108,7 @@
"c9.ide.recentfiles": "#7c099abf40",
"c9.ide.remote": "#301d2ab519",
"c9.ide.processlist": "#2b12cd1bdd",
"c9.ide.run": "#d661a7b847",
"c9.ide.run": "#bf68394c6f",
"c9.ide.run.build": "#0598fff697",
"c9.ide.run.debug.xdebug": "#054367574c",
"c9.ide.save": "#25a63f31e2",
@ -121,6 +121,6 @@
"c9.ide.undo": "#b028bcb4d5",
"c9.ide.upload": "#e4351f5a2b",
"c9.ide.welcome": "#5b86c44e92",
"c9.ide.guide": "#df7c89e449"
"c9.ide.guide": "#19f6087429"
}
}

Wyświetl plik

@ -3,6 +3,7 @@ module.exports = function (vfs, options, register) {
var net = require("net");
var Stream = require('stream');
var path = require("path");
var SOCKET = process.platform == "win32"
? "\\\\.\\pipe\\.c9\\bridge.socket"
@ -74,7 +75,6 @@ module.exports = function (vfs, options, register) {
clients.push(client);
}
api
var clients = [];
var stream = new Stream();
stream.readable = true;
@ -89,10 +89,17 @@ module.exports = function (vfs, options, register) {
var unixServer = net.createServer(registerClient);
unixServer.listen(SOCKET);
var socketDirExists = false;
unixServer.on("error", function(err){
if (err.code == "EADDRINUSE") {
createListenClient(api);
}
else if (err.code == "EACCES" && !socketDirExists) {
vfs.mkdirP(path.dirname(SOCKET), {}, function() {
socketDirExists = true;
unixServer.listen(SOCKET);
});
}
else
api.onError(err);
});

Wyświetl plik

@ -40,14 +40,6 @@ require(["lib/architect/architect", "lib/chai/chai", "/vfs-root", "/vfs-home"],
},
"plugins/c9.cli.bridge/bridge-client",
// Mock plugins
{
consumes: [],
provides: [
"preferences", "ui"
],
setup: expect.html.mocked
},
{
consumes: ["bridge", "bridge.client"],
provides: [],

Wyświetl plik

@ -122,9 +122,9 @@ define(function(require, module, exports) {
emit("quit");
}
function toExternalPath(path) {
function toExternalPath(path, sep) {
if (plugin.platform == "win32")
path = path.replace(/^[/]+/, "").replace(/[/]+/g, "\\");
path = path.replace(/^[/]+/, "").replace(/[/]+/g, sep || "\\");
return path;
}

Wyświetl plik

@ -208,20 +208,21 @@ define(function(require, exports, module) {
var reHome, reWorkspace, homeSub;
plugin.$initPaths = function(home, workspaceDir) {
reHome = new RegExp("^" + plugin.escapeRegExp(home) + "(/|/?$)");
var pre = c9.platform == "win32" ? "/?" : "";
reHome = new RegExp("^" + pre + plugin.escapeRegExp(home) + "(/|/?$)");
var wd = workspaceDir.replace(/\/?$/, "");
reWorkspace = new RegExp("^" + plugin.escapeRegExp(wd) + "(/|/?$)");
reWorkspace = new RegExp("^" + pre + plugin.escapeRegExp(wd) + "(/|/?$)");
homeSub = "~/";
if (home == workspaceDir) {
reHome = new RegExp("^(" + plugin.escapeRegExp(home) + "|~)(/|/?$)");
reHome = new RegExp("^(" + pre + plugin.escapeRegExp(home) + "|~)(/|/?$)");
homeSub = "/";
reWorkspace = null;
} else if (reHome.test(workspaceDir)) {
reWorkspace = new RegExp("^" +
reWorkspace = new RegExp("^" + pre +
plugin.escapeRegExp(workspaceDir.replace(reHome, "~/")) + "(/|/?$)"
);
} else if (reWorkspace.test(home)) {
reHome = new RegExp("^(" + plugin.escapeRegExp(home) + "|~)(/|/?$)");
reHome = new RegExp("^(" + pre + plugin.escapeRegExp(home) + "|~)(/|/?$)");
homeSub = home.replace(reWorkspace, "/").replace(/\/?$/, "/");
reWorkspace = null;
}

Wyświetl plik

@ -746,7 +746,7 @@ define(function(require, exports, module) {
} else if (node.status == "loading") {
plugin.on("readdir", function listener(e) {
if (e.path == subPath) {
plugin.on("readdir", listener);
plugin.off("readdir", listener);
recur();
}
});

Wyświetl plik

@ -462,8 +462,9 @@ require(["lib/architect/architect", "lib/chai/chai", "/vfs-root", "events"],
fs.writeFile(before, text, function(err) {
expect(fsCache.findNode(before), "start").to.exist;
expect(fsCache.findNode(after), "start").to.not.exist;
fs.rename(before, after, function() {
expect(fsCache.findNode(after), "afer").to.exist;
expect(fsCache.findNode(after), "after").to.exist;
expect(fsCache.findNode(before), "before").to.not.exist;
fs.rmfile(after, function(){
fsCache.off("update", c1);
@ -486,6 +487,7 @@ require(["lib/architect/architect", "lib/chai/chai", "/vfs-root", "events"],
fsCache.on("update", c1);
fs.writeFile(before, text, function(err) {
expect(err).to.not.ok;
expect(fsCache.findNode(before), "start").to.exist;
fs.rename(before, after, function() {
@ -500,11 +502,10 @@ require(["lib/architect/architect", "lib/chai/chai", "/vfs-root", "events"],
throw new Error("Wrong Event Count: "
+ count + " of 2");
});
// Disabled: test fails only on CI server...
});
});
});
it.skip("should recursively update the nodes in cache when a dir is renamed", function(done) {
it("should recursively update the nodes in cache when a dir is renamed", function(done) {
fs.rmdir("/rdir", {recursive:true}, function(){
fs.copy("/dir", "/dir2", {recursive: true}, function(err) {
if (err) throw err.message;
@ -535,7 +536,7 @@ require(["lib/architect/architect", "lib/chai/chai", "/vfs-root", "events"],
+ count + " of 3");
});
});
})
});
});
});
});

Wyświetl plik

@ -18,12 +18,6 @@ require(["lib/architect/architect", "lib/chai/chai", "/vfs-root"],
"plugins/c9.vfs.client/endpoint",
"plugins/c9.ide.auth/auth",
//Mock Plugins
{
consumes: ["Plugin"],
provides: ["auth.bootstrap", "info", "dialog.error"],
setup: expect.html.mocked
},
{
consumes: ["fs"],
provides: [],
@ -285,6 +279,8 @@ require(["lib/architect/architect", "lib/chai/chai", "/vfs-root"],
expect(exists).ok;
fs.rmdir(vpath, {}, function(err, meta) {
if (err.code == "EACCES") // node sends EACCES on windows
err.code = "ENOTDIR";
expect(err).property("code").equal("ENOTDIR");
done();
});

Wyświetl plik

@ -2,7 +2,7 @@
"use client";
require(["lib/architect/architect", "lib/chai/chai"], function (architect, chai) {
require(["lib/architect/architect", "lib/chai/chai", "/vfs-root"], function (architect, chai, vfsRoot) {
var expect = chai.expect;
expect.setupArchitectTest([
@ -11,7 +11,8 @@ require(["lib/architect/architect", "lib/chai/chai"], function (architect, chai)
startdate: new Date(),
debug: true,
hosted: true,
local: false
local: false,
platform: vfsRoot.indexOf(":") == -1 ? "linux" : "win32"
},
"plugins/c9.core/http-xhr",
"plugins/c9.core/ext",
@ -19,14 +20,8 @@ require(["lib/architect/architect", "lib/chai/chai"], function (architect, chai)
"plugins/c9.vfs.client/vfs_client",
"plugins/c9.vfs.client/endpoint",
"plugins/c9.ide.auth/auth",
// Mock plugins
{
consumes: [],
provides: ["auth.bootstrap", "info", "dialog.error"],
setup: expect.html.mocked
},
{
consumes: ["proc"],
consumes: ["proc", "c9"],
provides: [],
setup: main
}
@ -34,6 +29,7 @@ require(["lib/architect/architect", "lib/chai/chai"], function (architect, chai)
function main(options, imports, register) {
var proc = imports.proc;
var c9 = imports.c9;
describe('proc', function() {
describe('spawn()', function() {
@ -117,10 +113,15 @@ require(["lib/architect/architect", "lib/chai/chai"], function (architect, chai)
});
describe('pty()', function() {
this.timeout(30000);
if (c9.platform == "win32")
return it.skip("Terminal Test", function(done) { done(); });
it("Terminal Test", function(done) {
var look = "--color=auto";
if (c9.platform == "win32")
return done;
var args = ["-is"];
proc.pty("bash", {
args: args,

Wyświetl plik

@ -14,8 +14,8 @@ define(function(require, module, exports) {
allowClose: false,
modal: true,
elements: [
{ type: "button", id: "cancel", caption: "Cancel", hotkey: "ESC", onclick: function(){ plugin.hide() } },
{ type: "button", id: "ok", caption: "OK", color: "green", "default": true, onclick: function(){ plugin.hide() } }
{ type: "button", id: "ok", caption: "OK", color: "green", "default": true, onclick: function(){ plugin.hide() } },
{ type: "button", id: "cancel", caption: "Cancel", hotkey: "ESC", onclick: function(){ plugin.hide() } }
]
});

Wyświetl plik

@ -67,13 +67,6 @@
Show files in tree
</a:checkbox>
<a:filler />
<a:button
id = "btnCancel"
class = "btn-red"
skin = "btn-default-css3"
width = "120"
caption = "Cancel"
/>
<a:button
id = "btnChoose"
class = "btn-green"
@ -81,6 +74,13 @@
caption = "Save"
skin = "btn-default-css3"
/>
<a:button
id = "btnCancel"
class = "btn-red"
skin = "btn-default-css3"
width = "120"
caption = "Cancel"
/>
</a:hbox>
</a:vbox>
</a:window>

Wyświetl plik

@ -47,17 +47,17 @@
</div>
<a:hbox edge="23 0 10" pack="end" padding="8">
<a:button
id = "btnCancel"
skin = "btn-default-css3"
caption = "Cancel"
/>
<a:button
id = "btnChoose"
class = "btn-green"
caption = "OK"
skin = "btn-default-css3"
/>
<a:button
id = "btnCancel"
skin = "btn-default-css3"
caption = "Cancel"
/>
</a:hbox>
</a:vbox>
</a:window>

Wyświetl plik

@ -1,6 +1,6 @@
define(function(require, module, exports) {
main.consumes = [
"Plugin", "menus", "ui"
"Plugin", "menus", "ui", "settings"
];
main.provides = ["editors"];
return main;
@ -9,6 +9,7 @@ define(function(require, module, exports) {
var ui = imports.ui;
var Plugin = imports.Plugin;
var menus = imports.menus;
var settings = imports.settings;
var extname = require("path").extname;
var basename = require("path").basename;
@ -69,6 +70,11 @@ define(function(require, module, exports) {
function findEditorByFilename(fn) {
var ext = extname(fn).substr(1).toLowerCase();
var filename = basename(fn).toLowerCase();
// Check custom user settings first for preferred editor
var customEditor = settings.get("user/tabs/editorTypes/@" + ext);
if (customEditor) return customEditor;
var editor = fileExtensions[fn] && fileExtensions[fn][0]
|| fileExtensions[filename] && fileExtensions[filename][0]
|| fileExtensions[ext] && fileExtensions[ext][0]

Wyświetl plik

@ -385,6 +385,7 @@ define(function(require, module, exports) {
open({
path: name,
focus: true,
active: true,
pane: e.pane,
value: "",
@ -1077,6 +1078,12 @@ define(function(require, module, exports) {
// options.document.filter = true;
options.editorType = type;
// Don't proceed if findEditorByFilename returned "none"
if (editor === "none") {
alert("Can't open " + basename(path) + ": file format unsupported");
return callback(new Error("File not supported"));
}
// Create the tab
tab = createTab(options);

Wyświetl plik

@ -730,7 +730,7 @@
@breakpoint-list-item-border-top: transparent;
@breakpoint-list-item-padding: 1px 10px 0 7px;
@breakpoint-list-item-hover-color: darken(#e0e3e8, @darken-chrome);
@breakpoint-list-item-hover-background: darken(#F6F6F6, @darken-chrome);
@breakpoint-list-item-hover-background: darken(#252525, @darken-chrome);
@breakpoint-list-item-hover-border-top: transparent;
// Breakpoint Condition Dialog
@ -774,7 +774,7 @@
@immediate-font-smoothing: false;
@immediate-dark-row-border-color: darken(rgb(29, 28, 28), @darken-chrome);
@immediate-dark-return: darken(#252525, @darken-chrome);
@immediate-dark-return: darken(#FFFFFF, @darken-chrome);
@immediate-dark-warn: yellow;
@immediate-dark-error: red;
@immediate-dark-property: darken(#BEDB18, @darken-chrome);
@ -1658,12 +1658,12 @@
@stats-button-width: 100px;
@stats-button-margin-left: 0;
@stats-button-padding: 2px 5px 2px 7px;
@stats-button-border-left: 1px solid #e0e0e0;
@stats-button-border-right: 1px solid #e0e0e0;
@stats-button-border-left: 1px solid #1c1c1c;
@stats-button-border-right: 1px solid #1c1c1c;
@stats-button-box-shadow: none;
@stats-button-color: #666666;
@stats-button-hover-background: #E9E9E9;
@stats-button-active-background: white;
@stats-button-hover-background: #494949;
@stats-button-active-background: #494949;
@stats-button-active-box-shadow: 0px 0px 10px 0px rgba(0, 0, 0, 0.09);
@stats-button-item-padding: 4px 0 0 0;

Wyświetl plik

@ -5,9 +5,10 @@
}
.bartools .c9-toolbarbutton-glossymenuDown{
background-color: #ffffff;
background-color: #494949;
box-shadow: 0px 3px 15px 0px rgba(0, 0, 0, 0.29);
border: 1px solid #dedede;
border-left: 1px solid #252525;
border-right: 1px solid #252525;
}
.output .toolbar .c9-toolbarbutton-glossyOver{

Wyświetl plik

@ -120,6 +120,11 @@ define(function(require, exports, module) {
* @return {Object}
*/
getLastPing: apiFunction.bind(null, "getLastPing"),
/**
* Add a hook for ping.complete
*/
onPingComplete: apiFunction.bind(null, "onPingComplete"),
});
register(null, { metrics: plugin });

Wyświetl plik

@ -0,0 +1,259 @@
#c9_ide_restore {
display: none;
z-index: 1000000;
position: absolute;
height: 100%;
left: 0;
right: 0;
top: 0;
bottom: 0;
}
#c9_ide_restore .timeout a {
color: #FFDE75;
text-decoration: none;
}
#c9_ide_restore .timeout {
position: relative;
background: #DA7A30;
z-index: 10000000;
color: white;
padding: 5px;
border-radius: 3px;
margin: 10px;
text-align: center;
display: none;
}
/* progress 3C7B0D*/
#restoring {
font-style: normal;
height: 100%;
width: 100%;
position: fixed;
text-align: center;
z-index: 100000;
left: 0;
top: 0;
.font-smoothing(~"antialiased !important");
background: white url("@{image-path}/loadingbgrepeat.png");
background-size: 1px 8px;
}
.dark #restoring{
background: black url("@{image-path}/loadingbgrepeat_dark.png");
background-size: 1px 8px;
}
#restoring .loading-progress {
font-size: 31px;
color: #4A8532;
height: 37px;
position: relative;
margin: 252px 0 0 0;
top: 30%;
}
#restoring .loading-msg {
color: #717171;
.font-smoothing(true);
margin: 58px 0 10px;
}
#restoring .loading-details{
margin: 3px 0 0 0;
font-size: 14px;
color: #858E91;
.font-smoothing(true);
font-weight: bold;
}
.stickynote {
position: absolute;
top: 30%;
left: 50%;
margin: 0px -261px;
z-index : 10000000;
.transform(~"rotate(2deg)");
}
.stickynote.casual{
bottom: 50px;
right: 50px;
left: auto;
top: auto;
margin: 0;
}
.stickynote .paper {
color: black;
width: 284px;
/*color: #f1f1f1;*/
background: #FFDE75;
padding: 25px 20px 10px 20px;
box-shadow: 1px 1px 15px rgba(0,0,0,0.12);
// font-family : Tahoma;
font-size : 15px;
text-align : left;
.font-smoothing(true);
}
.stickynote strong {
font-size: 17px;
}
.stickynote a.restore-upsell {
text-decoration: none;
display: inline-block;
padding: 5px 10px 8px 10px;
background: #39A6D7;
border-radius: 5px;
color: white;
margin-bottom: -10px;
}
.stickynote a.restore-upsell:hover {
background: #0FB6FF;
}
.stickynote .tape {
position: absolute;
top: -15px;
right: 80px;
width: 130px;
height: 35px;
background-color: rgba(255, 255, 255, 0.6);
border-left: 1px dashed rgba(0, 0, 0, 0.1);
border-right: 1px dashed rgba(0, 0, 0, 0.1);
.box-shadow(~"0px 0px 1px 0px rgba(204, 204, 204, 0.28)");
.transform(~"rotate(-2deg) skew(0,0) translate(0%,-5px)");
}
.stickynote .left-shadow {
width: 140px;
height: 140px;
bottom: -5px;
left: -12px;
position: absolute;
z-index: -6;
display: inline-block;
.box-shadow(~"-10px -10px 10px rgba(0, 0, 0, 0.12)");
.transform(~"scale(1) rotate(274deg) translate(20px, 25px) skew(9deg, 0deg)");
}
.stickynote .right-shadow {
width: 140px;
height: 140px;
bottom: -13px;
right: -4px;
position: absolute;
z-index: -6;
display: inline-block;
.box-shadow(~"-10px -10px 10px rgba(0, 0, 0, 0.12)");
.transform(~"scale(1) rotate(184deg) translate(20px, 25px) skew(9deg, 0deg)");
}
/*
Copyright (c) 2010-2012 Ivan Vanderbyl
Originally found at http://ivan.ly/ui
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
/* Webkit animation keyframes */
@-webkit-keyframes animate-stripes {
to {
background-position: 0 0;
}
from {
background-position: 44px 0;
}
}
@-moz-keyframes animate-stripes {
to {
background-position: 0 0;
}
from {
background-position: 36px 0;
}
}
/* Bar which is placed behind the progress */
.ui-progress-bar {
/* Usual setup stuff */
position: relative;
width: 240px;
margin: 15px auto 10px;
height: 8px;
/* Pad right so we don't cover the borders when fully progressed */
/* For browser that don't support gradients, we'll set a blanket background colour */
background-color: rgba(157, 167, 171, 0.42);
.border-radius(~"10px");
}
.ui-progress-bar.blue .ui-progress {
background-color: #339BB9!important;
border: 1px solid #287a91;
}
.ui-progress-bar.error .ui-progress {
background-color: #C43C35 !important;
border: 1px solid #9c302a;
}
.ui-progress-bar.warning .ui-progress {
background-color: #D9B31A!important;
border: 1px solid #ab8d15;
}
.ui-progress-bar.success .ui-progress {
background-color: #57A957!important;
border: 1px solid #458845;
}
.ui-progress-bar.transition .ui-progress {
.transition(~"background-color 0.5s ease-in, border-color 1.5s ease-out, box-shadow 1.5s ease-out")
}
.ui-progress-bar .ui-progress {
/* Usual setup stuff */
position: relative;
display: block;
overflow: hidden;
/* Height should be 2px less than .ui-progress-bar so as to not cover borders and give it a look of being inset */
height: 8px;
/* Rounds the ends, we specify an excessive amount to make sure they are completely rounded */
/* Adjust to your liking, and don't forget to adjust to the same amount in .ui-progress-bar */
.border-radius(~"10px");
/* Webkit background stripes and gradient */
background: -webkit-gradient(linear, 0 0, 44 44, color-stop(0, rgba(0, 0, 0, 0.17)), color-stop(0.25, rgba(0, 0, 0, 0.17)), color-stop(0.26, rgba(0, 0, 0, 0)), color-stop(0.5, rgba(0, 0, 0, 0)), color-stop(0.51, rgba(0, 0, 0, 0.17)), color-stop(0.75, rgba(0, 0, 0, 0.17)), color-stop(0.76, rgba(0, 0, 0, 0)), color-stop(1, rgba(0, 0, 0, 0))), -webkit-gradient(linear, left bottom, left top, color-stop(0, rgba(0, 0, 0, 0)), color-stop(1, rgba(0, 0, 0, 0.35))), #EAF9FF;
background: -moz-repeating-linear-gradient(top left -30deg, rgba(0, 0, 0, 0.17), rgba(0, 0, 0, 0.17) 15px, rgba(0, 0, 0, 0) 15px, rgba(0, 0, 0, 0) 30px), -moz-linear-gradient(rgba(0, 0, 0, 0.25) 0%, rgba(0, 0, 0, 0) 100%), #EAF9FF;
/* Set the background size so the stripes work correctly */
-webkit-background-size: 44px 44px;
-moz-background-size: 36px 36px;
/* Animate */
-moz-animation: animate-stripes 2s linear infinite;
-webkit-animation: animate-stripes 2s linear infinite;
-o-animation: animate-stripes 2s linear infinite;
-ms-animation: animate-stripes 2s linear infinite;
-khtml-animation: animate-stripes 2s linear infinite;
animation: animate-stripes 2s linear infinite;
/* Style status label */
top:0px;
left:0px;
}
.dark .ui-progress-bar .ui-progress {
background: -webkit-gradient(linear, 0 0, 44 44, color-stop(0, rgba(0, 0, 0, 0.17)), color-stop(0.25, rgba(0, 0, 0, 0.17)), color-stop(0.26, rgba(0, 0, 0, 0)), color-stop(0.5, rgba(0, 0, 0, 0)), color-stop(0.51, rgba(0, 0, 0, 0.17)), color-stop(0.75, rgba(0, 0, 0, 0.17)), color-stop(0.76, rgba(0, 0, 0, 0)), color-stop(1, rgba(0, 0, 0, 0))), -webkit-gradient(linear, left bottom, left top, color-stop(0, rgba(0, 0, 0, 0)), color-stop(1, rgba(0, 0, 0, 0.35))), #4ACBFD;
background: -moz-repeating-linear-gradient(top left -30deg, rgba(0, 0, 0, 0.17), rgba(0, 0, 0, 0.17) 15px, rgba(0, 0, 0, 0) 15px, rgba(0, 0, 0, 0) 30px), -moz-linear-gradient(rgba(0, 0, 0, 0.25) 0%, rgba(0, 0, 0, 0) 100%), #4ACBFD;
/* Set the background size so the stripes work correctly */
-webkit-background-size: 44px 44px;
-moz-background-size: 36px 36px;
}

Wyświetl plik

@ -0,0 +1,37 @@
<div id="c9_ide_restore">
<div class="timeout">This is taking longer than expected. If you think there might be an issue please contact <a href="https://c9.io/support">support</a>.</div>
<div id="loadingide"></div>
<div class="stickynote">
<div class="tape"></div>
<div class="left-shadow"></div>
<div class="right-shadow"></div>
<div class="paper">
<strong>What's going on here?</strong>
<p>
We create a separate virtual machine for each workspace.
In order to provide a free
service for everyone, we hibernate workspaces of
<nobr>non-premium</nobr> users after about one week of inactivity.
This is because the virtual machines constantly use resources even if
the workspace is not actively used.
<p>
Please wait a moment while we wake up your workspace. It will
be just as you left it.
<p>
<a href="/upgrade/webide" target="_blank">Upgrade to premium</a> to make sure your workspace never
goes into hibernate.
</div>
</div>
<div id="restoring">
<div id="content" class="loading-progress">
<div class="loading-details"></div>
<div class="ui-progress-bar ui-container" id="progress_bar">
<div class="ui-progress" style="width: 100%;">
<!--<span class="ui-label" style="display:none;"></span>-->
</div>
</div>
<div class="loading-msg">Waking up your workspace from hibernation.</div>
</div>
</div>
</div>

Wyświetl plik

@ -0,0 +1,298 @@
define(function(require, exports, module) {
"use strict";
main.consumes = [
"Plugin", "ui", "vfs.endpoint", "vfs", "layout", "anims", "c9",
"c9.analytics", "layout"
];
main.provides = ["restore"];
return main;
function main(options, imports, register) {
var Plugin = imports.Plugin;
var ui = imports.ui;
var vfs = imports.vfs;
var c9 = imports.c9;
var anims = imports.anims;
var layout = imports.layout;
var endpoint = imports["vfs.endpoint"];
var analytics = imports["c9.analytics"];
/***** Initialization *****/
var plugin = new Plugin("Ajax.org", main.consumes);
var el, msgEl, detailsEl, descriptionEl, stickynoteEl, uiProgress;
var timeoutTimer, timeoutEl;
var MAX_HOT_WORKSPACES = "three";
var TIMEOUT_TIME = 15 * 60 * 1000;
var STATE_CREATED = 1;
var STATE_READY = 2;
var STATE_MIGRATING = 4;
var STATE_MARKED_FOR_ARCHIVE = 20;
var STATE_ARCHIVING = 21;
var STATE_ARCHIVED = 22;
var STATE_MARKED_FOR_RESTORE = 23;
var STATE_RESTORING = 24;
var STATE_RESIZING = 31;
var stateMessages = {};
stateMessages[STATE_CREATED] = "Creating your new workspace";
stateMessages[STATE_READY] = "Starting your workspace";
stateMessages[STATE_MIGRATING] = "Migrating your workspace to our new backend";
stateMessages[STATE_MARKED_FOR_ARCHIVE] =
stateMessages[STATE_ARCHIVING] = "Archiving your workspace";
stateMessages[STATE_ARCHIVED] =
stateMessages[STATE_MARKED_FOR_RESTORE] =
stateMessages[STATE_RESTORING] = "Waking up your workspace from hibernation.";
stateMessages[STATE_RESIZING] = "Resizing your workspace";
var defaultStateMessage = "Opening your workspace";
var description =
"<strong>You could be coding right now</strong>\n" +
"<p>\n" +
"In order to provide a free\n" +
"service for everyone, we stop workspaces after a while.\n" +
"<p>\n" +
"Premium plans offer active workspaces, which ensure that the " + MAX_HOT_WORKSPACES + "\n" +
"most recently used workspaces are never stopped.\n" +
"<p>\n" +
"<a class='restore-upsell' data-link-id='upsell-webide-migrate' href='" + options.ideBaseUrl + "/account/upgrade/webide' target='_blank'>Upgrade to premium now</a>";
var premiumStoppedDescription =
"<strong>Swapping in Workspace</strong>\n" +
"<p>\n" +
"This workspace is not one of your active workspaces and has been stopped.\n" +
"<p>\n" +
"The " + MAX_HOT_WORKSPACES + " most recently used workspaces are never stopped.\n" +
"<p>\n" +
"As part of a team plan you have more active workspaces.\n" +
"<p>\n" +
"<a class='restore-upsell' data-link-id='upsell-teams-migrate' href='" + options.ideBaseUrl + "/account/billing' target='_blank'>Upgrade to team plans now</a>";
var migrateDescription =
"<strong>What's going on here?</strong>\n" +
"<p>\n" +
"We rolled out a completely new backend infrastructure with \n" +
"improved performance and lots of new features.\n" +
"<p>\n" +
"With the new backend you get:\n" +
"<ul>\n" +
"<li>an Ubuntu VM</li>\n" +
"<li>root access using sudo</li>\n" +
"<li>ability to run services</li>\n" +
"<li>ability to install packages</li>\n" +
"</ul>\n" +
"<p>\n" +
"Please wait a moment while we move your workspace. It will\n" +
"be just as you left it.\n";
var premiumDescription =
"<strong>What's going on here?</strong>\n" +
"<p>\n" +
"We're migrating your premium workspace to a new server \n" +
"to ensure optimal performance.\n" +
"<p>\n" +
"Please wait a moment while we move your workspace. It will\n" +
"be just as you left it.\n";
var resizeDescription =
"<strong>What's going on here?</strong>\n" +
"<p>\n" +
"We're resizing your workspace\n" +
"to be exactly as you specified.\n" +
"<p>\n" +
"Please wait a moment while we resize your workspace.\n" +
"It will be just as you left it.\n";
var stateDescriptions = {
free: { casual: [STATE_MIGRATING, STATE_RESIZING] },
premium: { casual: [STATE_MIGRATING, STATE_MARKED_FOR_ARCHIVE, STATE_ARCHIVING, STATE_ARCHIVED, STATE_MARKED_FOR_RESTORE, STATE_RESTORING, STATE_RESIZING] },
};
stateDescriptions.free[STATE_CREATED] = "";
stateDescriptions.free[STATE_READY] = description;
stateDescriptions.free[STATE_MIGRATING] = migrateDescription; // different location
stateDescriptions.free[STATE_MARKED_FOR_ARCHIVE] = description;
stateDescriptions.free[STATE_ARCHIVING] = description;
stateDescriptions.free[STATE_ARCHIVED] = description;
stateDescriptions.free[STATE_MARKED_FOR_RESTORE] = description;
stateDescriptions.free[STATE_RESTORING] = description;
stateDescriptions.free[STATE_RESIZING] = resizeDescription; // different location
stateDescriptions.premium[STATE_CREATED] = "";
stateDescriptions.premium[STATE_READY] = premiumStoppedDescription;
stateDescriptions.premium[STATE_MIGRATING] = migrateDescription; // different location
stateDescriptions.premium[STATE_MARKED_FOR_ARCHIVE] = premiumDescription; // different location
stateDescriptions.premium[STATE_ARCHIVING] = premiumDescription; // different location
stateDescriptions.premium[STATE_ARCHIVED] = premiumDescription; // different location
stateDescriptions.premium[STATE_MARKED_FOR_RESTORE] = premiumDescription; // different location
stateDescriptions.premium[STATE_RESTORING] = premiumDescription; // different location
stateDescriptions.premium[STATE_RESIZING] = resizeDescription; // different location
var loaded = false;
function load() {
if (loaded) return false;
loaded = true;
endpoint.on("restore", showRestore);
vfs.on("connect", hideRestore);
}
var drawn = false;
function draw() {
if (drawn) return false;
drawn = true;
ui.insertCss(require("text!./restore.css"), plugin);
ui.insertHtml(null, require("text!./restore.html"), plugin);
el = document.getElementById("c9_ide_restore");
msgEl = document.querySelector("#c9_ide_restore .loading-msg");
detailsEl = document.querySelector("#c9_ide_restore .loading-details");
descriptionEl = document.querySelector("#c9_ide_restore .paper");
stickynoteEl = document.querySelector("#c9_ide_restore .stickynote");
uiProgress = document.querySelector("#progress_bar .ui-progress");
timeoutEl = document.querySelector("#c9_ide_restore .timeout");
}
/***** Methods *****/
var progress, maxProgress, run = 0, timer;
function animateProgress(progress, callback) {
anims.animate(uiProgress, {
width: progress + "%",
timingFunction: "cubic-bezier(.02, .01, .47, 1)",
duration: "1s"
}, callback);
}
function walk(loopId) {
if (loopId != run) return;
if (progress > 100)
return;
if (progress > maxProgress)
return (timer = setTimeout(walk.bind(null, loopId), 500));
animateProgress(progress++, function(){
timer = setTimeout(walk.bind(null, loopId), 10);
});
}
function showTimeout(){
timeoutEl.style.display = "block";
}
function showRestore(state) {
draw();
c9.startLoadTime = -1;
if (el.style.display != "block") {
uiProgress.style.width = 0;
progress = 6;
maxProgress = 10;
}
var isDark = layout.theme.indexOf("dark") > -1;
if (isDark)
el.classList.add("dark");
else
el.classList.remove("dark");
var descriptions = stateDescriptions[state.premium ? "premium" : "free"];
var description = descriptions[state.projectState || STATE_ARCHIVED];
msgEl.innerText = stateMessages[state.projectState || STATE_ARCHIVED] || defaultStateMessage;
if (description) {
descriptionEl.innerHTML = description;
var link = descriptionEl.querySelector("a.restore-upsell");
if (link)
link.addEventListener("click", trackLink, false);
stickynoteEl.style.display = "block";
if (~descriptions.casual.indexOf(state.projectState || STATE_ARCHIVED))
stickynoteEl.classList.add("casual");
else
stickynoteEl.classList.remove("casual");
}
else {
stickynoteEl.style.display = "none";
}
// we did not receive JSON
if (!state.progress || state.progress.nextProgress == 100)
return hideRestore();
// Display Message to the User
if (!/^Internal/.test(state.progress.message))
detailsEl.innerText = state.progress.message || "";
// Update Progress Bar
maxProgress = Math.max(maxProgress || 0, state.progress.nextProgress);
progress = Math.max(progress || 0, state.progress.progress);
walk(++run);
// Show Restore Screen
el.style.display = "block";
clearTimeout(timeoutTimer);
timeoutTimer = setTimeout(function(){
showTimeout();
}, TIMEOUT_TIME)
}
function trackLink(e) {
var el = e.target;
analytics.track("Clicked Internal Link", {
href: el.href,
linkId: el.dataset.linkId
});
}
function hideRestore() {
if (!el) return;
clearTimeout(timer);
progress = 101;
animateProgress(100, function(){
setTimeout(function(){
anims.animate(el, {
opacity: 0
}, function(){
el.style.display = "none";
el.style.opacity = 1;
timeoutEl.style.display = "";
});
}, 100);
});
}
/***** Lifecycle *****/
plugin.on("load", function(){
load();
});
/***** Register and define API *****/
/**
*
**/
plugin.freezePublicAPI({
show: showRestore,
hide: hideRestore
});
register(null, { "restore" : plugin });
}
});

Wyświetl plik

@ -205,8 +205,7 @@ define(function(require, exports, module) {
}
// Make sure home dir is marked correctly
path = path.replace(reHome, "~");
if (path[0] != "/") path = "/" + path;
path = util.normalizePath(path);
fs.stat(path, function(err, stat) {
if (err) {

Wyświetl plik

@ -251,7 +251,7 @@ define(function(require, exports, module) {
fsCache.model.getTooltipText = function(node) {
var size = node.size;
return node.label + (node.link ? " => " + node.link + "\n" : "")
return (node.label || node.path) + (node.link ? " => " + node.link + "\n" : "")
+ (size != undefined && !node.isFolder ? " | " + (
size < 0x400 ? size + " bytes" :
size < 0x100000 ? (size / 0x400).toFixed(2) + "KB" :

Wyświetl plik

@ -614,6 +614,8 @@ require(["lib/architect/architect", "lib/chai/chai", "/vfs-root"],
});
});
it('should copy a node', function(done) {
expect(fsCache.findNode("/dir/test.html")).to.ok;
expect(fsCache.findNode("/test.html")).to.not.ok;
tree.copy(
[fsCache.findNode("/dir/test.html")],
fsCache.findNode("/"),

Wyświetl plik

@ -1,7 +1,7 @@
define(function(require, exports, module) {
main.consumes = [
"Plugin", "fs", "settings", "preferences", "watcher", "tabManager",
"save", "dialog.question", "dialog.filechange", "threewaymerge"
"save", "dialog.question", "dialog.filechange", "threewaymerge", "collab"
];
main.provides = ["watcher.gui"];
return main;
@ -17,8 +17,15 @@ define(function(require, exports, module) {
var question = imports["dialog.question"];
var filechange = imports["dialog.filechange"];
var threeWayMerge = imports.threewaymerge.merge;
var collab = imports.collab;
var collabEnabled = options.collab;
var comparisonType = {
TIMESTAMP_AND_CONTENTS: "TIMESTAMP_AND_CONTENTS",
CONTENTS: "CONTENTS",
NONE: "NONE"
};
/***** Initialization *****/
@ -87,14 +94,14 @@ define(function(require, exports, module) {
}
if (tab.classList.contains("conflict")) {
addChangedTab(tab, true);
addChangedTab(tab, comparisonType.TIMESTAMP_AND_CONTENTS);
}
});
tabManager.on("open", function(e) {
initializeDocument(e.tab.document);
if (e.tab.classList.contains("conflict")) {
addChangedTab(e.tab, true);
addChangedTab(e.tab, comparisonType.TIMESTAMP_AND_CONTENTS);
}
}, plugin);
@ -119,33 +126,42 @@ define(function(require, exports, module) {
// Hook watcher events
// Update a file
// A change event sent from the watcher plugin
watcher.on("change", function(e) {
var tab = tabManager.findTab(e.path);
if (tab) {
// If collab picks this up and handles the change it will return false
if (emit("docChange", {tab: tab}) === false)
return;
if (collabEnabled && tab.editorType == "ace") {
/* If the lastChange (added by collab) was greater than 1 second ago set up a watch
To ensure that collab makes this change, if not report an error. The lastChange
check is to avoid a race condition if collab updates before this function runs */
if (!tab.meta.$lastCollabChange || tab.meta.$lastCollabChange < (Date.now() - 1000)) {
if (tab.meta.$collabChangeRegistered) {
clearTimeout(tab.meta.$collabChangeRegistered);
}
}
return false;
}
addChangedTab(tab, e.type === "change");
addChangedTab(tab, comparisonType.TIMESTAMP_AND_CONTENTS);
}
});
// Directory watcher is not needed if the normal watcher works
// watcher.on("directory", function(e) {
// var base = e.path;
// var files = e.files;
//
// // Rename all tabs
// tabManager.getTabs().forEach(function(tab) {
// if (tab.path && tab.path.indexOf(base) == 0) {
// // If the file is gone, lets notify the user
// if (files.indexOf(tab.path) == -1) {
// resolveFileDelete(tab);
// }
// }
// });
// });
collab.on("change", function (e) {
var tab = tabManager.findTab(e.path);
if (tab) {
addChangedTab(tab, comparisonType.NONE);
}
});
collab.on("resolveConflict", function (e) {
var tab = tabManager.findTab(e.path);
if (tab) {
var doc = tab.document;
var path = tab.path
resolveConflict(doc, path);
}
})
watcher.on("delete", function(e) {
var tab = tabManager.findTab(e.path);
@ -156,7 +172,13 @@ define(function(require, exports, module) {
/***** Methods *****/
function addChangedTab(tab, isSameFile) {
function resolveConflict(doc, path) {
doc.tab.classList.remove("conflict");
delete doc.meta.$merge;
delete changedPaths[path];
}
function addChangedTab(tab, doubleCheckComparisonType) {
// If we already have a dialog open, just update it, but mark the value dirty
if (changedPaths[tab.path]) {
if (changedPaths[tab.path].data)
@ -171,6 +193,9 @@ define(function(require, exports, module) {
return;
}
var doc = tab.document;
var path = tab.path;
changedPaths[tab.path] = { tab: tab, resolve: resolve };
// If the terminal is currently focussed, lets wait until
@ -178,25 +203,28 @@ define(function(require, exports, module) {
if (tabManager.focussedTab
&& tabManager.focussedTab.editorType == "terminal") {
tabManager.once("focus", function(){
addChangedTab(tab, false);
addChangedTab(tab, comparisonType.CONTENTS);
});
return;
}
function resolve() {
console.log("[watchers] resolved change event without dialog", path);
doc.tab.classList.remove("conflict");
delete doc.meta.$merge;
delete changedPaths[path];
if (collabEnabled && collab.send)
collab.send({type: "RESOLVE_CONFLICT", data: {docId: path}});
resolveConflict(doc, path);
}
var doc = tab.document;
var path = tab.path;
if (isSameFile)
checkByStatOrContents();
else
checkByContents();
switch (doubleCheckComparisonType) {
case comparisonType.TIMESTAMP_AND_CONTENTS:
checkByStatOrContents();
break;
case comparisonType.CONTENTS:
checkByContents();
break;
case comparisonType.NONE:
dialog();
break;
}
function dialog(data) {
if (!changedPaths[path])
@ -293,7 +321,6 @@ define(function(require, exports, module) {
function automerge(tab, data) {
if (!settings.getBool("user/general/@automerge"))
return false;
return merge(tab, data);
}
@ -313,8 +340,10 @@ define(function(require, exports, module) {
doc.meta.$mergeRoot = data;
// If the value on disk is the same as in the document, set the bookmark
if (mergedValue == data)
if (mergedValue == data) {
doc.undoManager.bookmark();
save.save(tab);
}
return true;
}
@ -339,6 +368,7 @@ define(function(require, exports, module) {
var doc = tab.document;
doc.setBookmarkedValue(data, true);
doc.meta.timestamp = Date.now() - settings.timeOffset;
save.save(tab);
changedPaths[path].resolve();
}
@ -579,9 +609,10 @@ define(function(require, exports, module) {
question.show(
"Always merge?",
"Always merge on file changes?",
"Enabling 'auto merge' makes it very easy to collaborate on "
+ "files with other people, especially when combined with "
+ "'auto save'. This setting can be controlled from the "
"With 'auto merge' enabled, if a file changes "
+ "on disk and you have unsaved changes in the IDE, "
+ "it will automatically attempt to merge your changes with the new file. "
+ "This setting can be controlled from the "
+ "settings panel as well.",
function() { // on yes
if (question.dontAsk)

Wyświetl plik

@ -17,6 +17,7 @@ define(function(require, exports, module) {
var https = require("https");
var http = require("http");
var mime = require("mime");
var Cache = require("c9/cache");
var metrics = imports.metrics;
var parseUrl = require("url").parse;
var debug = require("debug")("preview");
@ -24,43 +25,25 @@ define(function(require, exports, module) {
var staticPrefix = imports["connect.static"].getStaticPrefix();
function getProjectSession() {
function getRole(db) {
var roleCache = new Cache(10000, 10000);
return function(req, res, next) {
var session = req.session;
req.user = req.user || { id: -1 };
var username = req.params.username;
var projectname = req.params.projectname;
var ws = req.ws = username + "/" + projectname;
if (!session.ws)
session.ws = {};
req.projectSession = session.ws[ws];
if (
!req.projectSession ||
!req.projectSession.expires ||
req.projectSession.expires <= Date.now() ||
req.projectSession.uid != req.user.id
) {
req.projectSession = session.ws[ws] = {
expires: Date.now() + 10000
if (!req.user) {
req.user = {
id: -1
};
}
next();
};
}
function getRole(db) {
return function(req, res, next) {
if (req.projectSession.role) {
req.session = {};
var key = req.params.username + "/" + req.params.projectname + ":" + req.user.id;
var wsSession = roleCache.get(key);
if (wsSession) {
req.session = wsSession;
return next();
}
db.Project.findOne({
username: req.params.username,
name: req.params.projectname
@ -70,25 +53,27 @@ define(function(require, exports, module) {
if (err) return next(err);
project.getRole(req.user, function(err, role) {
project.getRole(req.user.id, function(err, role) {
if (err) return next(err);
var wsSession = {
role: role,
pid: project.id,
uid: req.user.id,
type: project.scm
};
roleCache.set(key, wsSession);
req.session = wsSession;
if (role == db.Project.ROLE_NONE) {
if (project.isPublicPreview())
role = db.Project.ROLE_VISITOR;
else if (req.user.id == -1)
return next(new error.Unauthorized());
else
return next(new error.Forbidden("You don't have access rights to preview this workspace"));
if (!project.isPublicPreview())
return next();
wsSession.role = db.Project.ROLE_VISITOR;
}
req.projectSession.role = role;
req.projectSession.pid = project.id;
req.projectSession.uid = req.user.id;
var type = project.scm;
req.projectSession.type = type;
if (type != "docker" || project.state != db.Project.STATE_READY)
if (wsSession.type != "docker" || project.state != db.Project.STATE_READY)
return next();
project.populate("remote", function(err) {
@ -100,10 +85,8 @@ define(function(require, exports, module) {
if (err) return next(err);
if (container.state == db.Container.STATE_RUNNING)
req.projectSession.proxyUrl = "http://" + meta.host + ":9000/" + meta.cid + "/home/ubuntu/workspace";
else
req.projectSession.expires = Date.now() + 1000;
wsSession.proxyUrl = "http://" + meta.host + ":9000/" + meta.cid + "/home/ubuntu/workspace";
next();
});
} else {
@ -114,26 +97,41 @@ define(function(require, exports, module) {
});
};
}
function checkRole(db) {
return function(req, res, next) {
var role = req.session.role;
if (role == db.Project.ROLE_NONE) {
if (req.user.id == -1)
return next(new error.Unauthorized());
else
return next(new error.Forbidden("You don't have access rights to preview this workspace"));
}
return next();
};
}
function getProxyUrl(getServer) {
return function(req, res, next) {
if (req.projectSession.proxyUrl) {
req.proxyUrl = req.projectSession.proxyUrl;
if (req.session.proxyUrl) {
req.proxyUrl = req.session.proxyUrl;
return next();
}
var server = req.projectSession.vfsServer;
var server = req.session.vfsServer;
if (!server) {
server = getServer();
if (!server || !server.url)
return next(new error.ServiceUnavailable("No VFS server found"));
server = req.projectSession.vfsServer = server.internalUrl || server.url;
server = req.session.vfsServer = server.internalUrl || server.url;
}
var url = server + "/" + req.projectSession.pid + "/preview";
var url = server + "/" + req.session.pid + "/preview";
req.proxyUrl = url;
next();
};
@ -222,9 +220,6 @@ define(function(require, exports, module) {
} else if (body.indexOf("ENOENT") !== -1 || statusCode == 404) {
next(new error.NotFound("File '" + path + "' could not be found!"));
} else {
if (req.session.ws)
delete req.session.ws[req.ws];
var json;
try {
json = JSON.parse(body);
@ -365,8 +360,8 @@ define(function(require, exports, module) {
register(null, {
"preview.handler": {
getProjectSession: getProjectSession,
getRole: getRole,
checkRole: checkRole,
getProxyUrl: getProxyUrl,
proxyCall: proxyCall
}

Wyświetl plik

@ -2,7 +2,7 @@ define(function(require, exports, module) {
"use strict";
main.consumes = [
"session",
"connect",
"db",
"c9.login",
"preview.handler",
@ -14,13 +14,12 @@ define(function(require, exports, module) {
return main;
function main(options, imports, register) {
var session = imports.session;
var connect = imports.connect;
var db = imports.db;
var ensureLoggedIn = imports["c9.login"].ensureLoggedIn();
var handler = imports["preview.handler"];
var userContent = imports["user-content.redirect"];
var getVfsServers = imports["vfs.serverlist"].getServers;
var ratelimit = require("c9/ratelimit");
var frontdoor = require("frontdoor");
var error = require("http-error");
@ -38,7 +37,7 @@ define(function(require, exports, module) {
api.use(userContent.redirectPreview());
session.use(api);
connect.use(api);
api.get("/:username/:projectname/:path*", {
params: {
@ -53,8 +52,8 @@ define(function(require, exports, module) {
requestTimeout(15*60*1000),
require("./lib/middleware/sanitize-path-param"),
require("./lib/middleware/block-dot-files"),
handler.getProjectSession(),
handler.getRole(db),
handler.checkRole(db),
handler.getProxyUrl(function() {
return getVfsServers()[0] || null;
}),
@ -63,8 +62,6 @@ define(function(require, exports, module) {
api.error(function(err, req, res, next) {
if (err instanceof error.Unauthorized) {
req.logout();
delete req.session.token;
return ensureLoggedIn(req, res, next);
}
return next(err);

Wyświetl plik

@ -0,0 +1,159 @@
#!/usr/bin/env node
/*global describe it before after beforeEach afterEach */
"use strict";
"use server";
require("c9/inline-mocha")(module);
require("c9/setup_paths");
var async = require("async");
var assert = require("assert");
var nock = require("nock");
var RestClient = require("c9/rest_client");
var baseTest = require('../c9.api/base_test');
var testDb = require("../c9.db.redis/test_redis");
var setupFixtures = require("test/lib/integration/setup");
describe(__filename, function() {
var db, serverList, client;
var testUser, testProject, testRemote, testContainer;
var loggedInUser = null;
before(function(next) {
baseTest({
config: "preview",
}, function(err, services) {
db = services.db;
serverList = services["vfs.serverlist"];
services.connect.useSetup(function(req, res, next) {
req.user = loggedInUser;
next();
});
client = new RestClient("localhost", services.apiPort, {
debug: false
});
testUser = require("test/lib/integration/db/user")(db);
testProject = require("test/lib/integration/db/project")(db);
testRemote = require("test/lib/integration/db/mock-remote")(db);
testContainer = require("test/lib/integration/db/mock-container")(db);
next(err);
});
});
after(function(next) {
testDb.stop(next);
});
beforeEach(function(next) {
serverList._testSetServerList([{
url: "http://vfs.c9.dev",
internalUrl: "http://vfs.c9.dev"
}]);
testDb.reset(next);
});
describe("preview", function() {
it("Should authorize users correctly", function(next) {
var user1, user2;
var public1, private1, private2;
// user1 user2
// user2/public
// user2/private1 user1 has no access
// user2/private2 user1 is collaborator
setupFixtures(
testUser.create(),
testUser.create(),
testProject.create(),
testRemote.create({type: "docker"}),
testContainer.create(),
testProject.create(),
testRemote.create({type: "docker"}),
testContainer.create(),
testProject.create(),
testRemote.create({type: "docker"}),
testContainer.create(),
function(ctx, next) {
user1 = ctx.users[0];
user2 = ctx.users[1];
public1 = ctx.projects[0];
private1 = ctx.projects[1];
private2 = ctx.projects[2];
next();
},
function(ctx, next) {
public1.owner = user2;
public1.visibility = "public";
public1.save(next);
},
function(ctx, next) {
private1.owner = user2;
private1.visibility = "private";
private1.save(next);
},
function(ctx, next) {
private2.owner = user2;
private2.visibility = "private";
private2.save(next);
},
function(ctx, next) {
db.WorkspaceMember.create(
private2,
user1.id,
db.WorkspaceMember.ACL_R,
db.Project.ROLE_COLLABORATOR, null, next
);
},
function(fixtures, teardown) {
/*
* Logged in Role Visibility ACTION
* =================================================================
* true none public view
* false none public view
* true none private forbidden
* false none private unauthorized
* true visitor/collaborator/admin public view
* true visitor/collaborator/admin private view
*/
var expect = [
{ uid: user1.id, role: db.Project.ROLE_NONE, p: public1, code: 200 },
{ uid: -1, role: db.Project.ROLE_NONE, p: public1, code: 200 },
{ uid: user1.id, role: db.Project.ROLE_NONE, p: private1, code: 403 },
{ uid: -1, role: db.Project.ROLE_NONE, p: private1, code: 302 }, // redirect to login page
{ uid: user1.id, role: db.Project.ROLE_COLLABORATOR, p: public1, code: 200 },
{ uid: user2.id, role: db.Project.ROLE_ADMIN, p: private2, code: 200 }
];
async.eachSeries(expect, function(expect, next) {
var path = "/" + expect.p.owner.name + "/" + expect.p.name + "/";
nock('http://vfs.c9.dev')
.get("/" + expect.p.id + "/preview/")
.reply(200, []);
loggedInUser = {
id: expect.uid
};
client.get(path, function (err, res) {
assert((err && err.code) == expect.code || expect.code == 200, "Wrong return code");
next();
});
}, function(err) {
if (err) return next(err);
teardown(next);
});
}
);
});
});
});

Wyświetl plik

@ -149,16 +149,16 @@ function plugin(options, imports, register) {
return next();
res.writeHead(200, {"Content-Type": "application/javascript"});
res.end("define(function(require, exports, module) { return '"
+ options.workspaceDir + "'; });");
res.end("define(function(require, exports, module) { return "
+ JSON.stringify(options.workspaceDir.replace(/\\/g, "/")) + "; });");
});
api.get("/vfs-home", function(req, res, next) {
if (!options.options.testing)
return next();
res.writeHead(200, {"Content-Type": "application/javascript"});
res.end("define(function(require, exports, module) { return '"
+ process.env.HOME + "'; });");
res.end("define(function(require, exports, module) { return "
+ JSON.stringify(process.env.HOME.replace(/\\/g, "/")) + "; });");
});
api.get("/update", function(req, res, next) {

Wyświetl plik

@ -446,6 +446,7 @@ require([
"metrics": {
getLastPing: function() { throw Error("Not implemented"); },
getLastest: function() { throw Error("Not implemented"); },
onPingComplete: function() { throw Error("Not implemented"); },
log: function() {},
increment: function() {}
},

Wyświetl plik

@ -82,7 +82,7 @@ updatePackage() {
}
updateAllPackages() {
c9packages=(`"$NODE" -e 'console.log(Object.keys(require("./package.json").c9plugins).join(" "))'`)
c9packages=`"$NODE" -e 'console.log(Object.keys(require("./package.json").c9plugins).join(" "))'`;
count=${#c9packages[@]}
i=0
for m in ${c9packages[@]}; do echo $m;
@ -95,7 +95,7 @@ updateAllPackages() {
updateNodeModules() {
echo "${magenta}--- Running npm install --------------------------------------------${resetColor}"
safeInstall(){
deps=(`"$NODE" -e 'console.log(Object.keys(require("./package.json").dependencies).join(" "))'`)
deps=`"$NODE" -e 'console.log(Object.keys(require("./package.json").dependencies).join(" "))'`;
for m in ${deps[@]}; do echo $m;
"$NPM" install --loglevel warn $m || true
done

Wyświetl plik

@ -91,8 +91,10 @@ function main(argv, config, onLoaded) {
var configs = options.argv._;
if (!configs.length)
configs = [config || DEFAULT_CONFIG];
if (options.argv.exclude && !Array.isArray(options.argv.exclude.length))
options.argv.exclude = [options.argv.exclude];
var exclude = options.argv.exclude || [];
if (typeof exclude == "string")
exclude = exclude.split(",");
var expanded = expandShortCuts(configs);
@ -120,7 +122,7 @@ function main(argv, config, onLoaded) {
function startConfigs(configs, done) {
async.each(configs, function(config, next) {
if (options.argv.exclude && options.argv.exclude.indexOf(config) > -1)
if (exclude && exclude.indexOf(config) > -1)
return next();
start(config, options, function(err, result, path) {
onLoaded && onLoaded(err, result, path);

Wyświetl plik

@ -125,7 +125,6 @@ module.exports = function(manifest, installPath) {
}
},
pricing: { containers: [] },
zuora: {},
localExtend: true,
extendDirectory: __dirname + "/../plugins"
};
@ -155,4 +154,6 @@ function readWin32Settings() {
if (!fs.existsSync(path.join(process.env.HOME, ".c9", "msys/bin/bash.exe")))
console.error(e);
}
process.env.CHERE_INVOKING = 1; // prevent cygwin from changing bash path
}