mirror of
https://github.com/apache/cordova-android.git
synced 2026-01-30 00:05:28 +08:00
Compare commits
427 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d654de809a | ||
|
|
86f9b618ef | ||
|
|
ec1cc70c8b | ||
|
|
a64203f817 | ||
|
|
f4b315961b | ||
|
|
3bc755de7c | ||
|
|
c5ffdff49b | ||
|
|
2829ed77cc | ||
|
|
f3885692d9 | ||
|
|
d7fc37d365 | ||
|
|
c3bdebdb83 | ||
|
|
9514a3ed94 | ||
|
|
050dd088cf | ||
|
|
26f0401fda | ||
|
|
e4e04927b6 | ||
|
|
6b3ef11715 | ||
|
|
cf0fdf5ac0 | ||
|
|
33614d1273 | ||
|
|
1f735935b9 | ||
|
|
8c14e33bb6 | ||
|
|
7375154228 | ||
|
|
1427c13504 | ||
|
|
5538a231a8 | ||
|
|
9be110683b | ||
|
|
cfc36140bc | ||
|
|
72e947e5c7 | ||
|
|
7320ce8ea7 | ||
|
|
3e07f26bc4 | ||
|
|
5415440829 | ||
|
|
15e19489e3 | ||
|
|
c3610aa43c | ||
|
|
c1ac3aa483 | ||
|
|
291f111913 | ||
|
|
c2a6dcb6bd | ||
|
|
3439746645 | ||
|
|
b10fe465ab | ||
|
|
480af2644c | ||
|
|
ecd2e06883 | ||
|
|
7cfb33d0ef | ||
|
|
9224ab1592 | ||
|
|
931a996dab | ||
|
|
98fe46757f | ||
|
|
6b6e887c2f | ||
|
|
b92303b1c9 | ||
|
|
731a36d3a0 | ||
|
|
342bbaa3ae | ||
|
|
56a3ee5fe6 | ||
|
|
d80d532a2a | ||
|
|
3aca14d530 | ||
|
|
aa2d3962bf | ||
|
|
f7c717e393 | ||
|
|
268fea58ee | ||
|
|
ba140a8a84 | ||
|
|
27f1181d53 | ||
|
|
f953e6adb8 | ||
|
|
ffd14fe7d9 | ||
|
|
66fa12a091 | ||
|
|
132650df28 | ||
|
|
81a77949fc | ||
|
|
7fbb2b195f | ||
|
|
1feaa7fed7 | ||
|
|
ac284fd39c | ||
|
|
e78db000c6 | ||
|
|
032ea8a8d3 | ||
|
|
fc63f66e89 | ||
|
|
832e626573 | ||
|
|
ce5d9a2ee8 | ||
|
|
77c51d3ae7 | ||
|
|
53dae45430 | ||
|
|
16343ffe70 | ||
|
|
b37498d5f6 | ||
|
|
9f41906895 | ||
|
|
fbeb379f1b | ||
|
|
2dcd50c11b | ||
|
|
30681eb772 | ||
|
|
52e575e1e7 | ||
|
|
890e12c306 | ||
|
|
6cbf6b7875 | ||
|
|
c255a84941 | ||
|
|
ce7d6d69d9 | ||
|
|
d5538b7076 | ||
|
|
cdfa13b265 | ||
|
|
e31c911c30 | ||
|
|
a658ea1573 | ||
|
|
a986e72338 | ||
|
|
162d9b6c2e | ||
|
|
9e3ccf4b3e | ||
|
|
6b71c2f392 | ||
|
|
0d313a3964 | ||
|
|
ddac192c4a | ||
|
|
69a03c2e16 | ||
|
|
2b128b85f7 | ||
|
|
879da03438 | ||
|
|
3f83fdbfc1 | ||
|
|
949152532c | ||
|
|
7ce46ed60c | ||
|
|
cb442364ca | ||
|
|
ac34bf1e54 | ||
|
|
a5d300c6ff | ||
|
|
533677df8b | ||
|
|
25be42d385 | ||
|
|
00f6d30e08 | ||
|
|
090822eb41 | ||
|
|
d9900a725d | ||
|
|
5cb01f2ae9 | ||
|
|
4be92f285a | ||
|
|
f9b89e98c2 | ||
|
|
f221441877 | ||
|
|
f2e8c00f49 | ||
|
|
525ce0e0ad | ||
|
|
2f7ffa3636 | ||
|
|
9ae3d2c074 | ||
|
|
bf13fd48ce | ||
|
|
3b99760a42 | ||
|
|
0e78dc35d8 | ||
|
|
c8bbdb23de | ||
|
|
7ee8117186 | ||
|
|
8237c41143 | ||
|
|
d52ca93ba6 | ||
|
|
8354651059 | ||
|
|
81cc3c260f | ||
|
|
4dc32e194b | ||
|
|
5a82dd5110 | ||
|
|
f20708a5e7 | ||
|
|
91cf78f183 | ||
|
|
0cde8819cf | ||
|
|
07632b0eeb | ||
|
|
4a7f825cfe | ||
|
|
4bc2051f44 | ||
|
|
34dde53506 | ||
|
|
7a09182446 | ||
|
|
eb8cf56e8e | ||
|
|
12a27643db | ||
|
|
c6ccde0558 | ||
|
|
16e3ebd87b | ||
|
|
94c096dd5b | ||
|
|
2e3e4ec3b2 | ||
|
|
6e222c3938 | ||
|
|
3b3bd9b6c9 | ||
|
|
4e3331ba66 | ||
|
|
b6c5a5fc9a | ||
|
|
94943a9a84 | ||
|
|
71e72f215d | ||
|
|
58cdfd86d0 | ||
|
|
dfa66b9dd4 | ||
|
|
d56ea25816 | ||
|
|
c91b272648 | ||
|
|
ca8bb75b40 | ||
|
|
36eab713a1 | ||
|
|
7133576fe9 | ||
|
|
effffcba1d | ||
|
|
404ce8bc3e | ||
|
|
a91bd095b0 | ||
|
|
fd6a1e5ed0 | ||
|
|
7d6ac87033 | ||
|
|
8aa813b862 | ||
|
|
95aa5c9f1c | ||
|
|
4319447cb5 | ||
|
|
50ea162251 | ||
|
|
9c239804d3 | ||
|
|
320e31bb10 | ||
|
|
8b55a16986 | ||
|
|
41125ea1e2 | ||
|
|
73219bf2d2 | ||
|
|
d6eb723b7f | ||
|
|
993d73762c | ||
|
|
48b51c451a | ||
|
|
3d191d5884 | ||
|
|
955133f173 | ||
|
|
c2cafb4b45 | ||
|
|
67f474ef42 | ||
|
|
cd6c0e1de9 | ||
|
|
92be0033a8 | ||
|
|
b934c1be6a | ||
|
|
145b50a320 | ||
|
|
a33cdc9c7b | ||
|
|
62101e85ff | ||
|
|
0a3714e5e0 | ||
|
|
86a2830d75 | ||
|
|
9300e97d2b | ||
|
|
3792f75281 | ||
|
|
a14c794255 | ||
|
|
aef96e95e8 | ||
|
|
cc860804f6 | ||
|
|
d8a19b5565 | ||
|
|
1c5b5e2ce6 | ||
|
|
2f24e42dc1 | ||
|
|
0c12aa163e | ||
|
|
ec47274fbd | ||
|
|
04ccb06e3f | ||
|
|
d31ee20ba5 | ||
|
|
9b25d45b93 | ||
|
|
d51abdd73e | ||
|
|
9ea8b2237a | ||
|
|
e86c2e5970 | ||
|
|
caeb86843d | ||
|
|
0f15608175 | ||
|
|
705991e5b0 | ||
|
|
b636874bd9 | ||
|
|
965e4e9b19 | ||
|
|
af77977fda | ||
|
|
e74baf188f | ||
|
|
663a71255f | ||
|
|
79aa3e159d | ||
|
|
95118398dd | ||
|
|
4d18a8e55f | ||
|
|
3bab41f138 | ||
|
|
f577af0886 | ||
|
|
aab47bd453 | ||
|
|
445ddd89fb | ||
|
|
6f21a96238 | ||
|
|
c47bcb2f54 | ||
|
|
b0b628ffc2 | ||
|
|
4b4a2e9f9e | ||
|
|
58afd0b604 | ||
|
|
4352456129 | ||
|
|
bb141a70e8 | ||
|
|
ff260c03ca | ||
|
|
297f862ccc | ||
|
|
141bbfb051 | ||
|
|
663a919ed1 | ||
|
|
483babe3bc | ||
|
|
b407641049 | ||
|
|
32e07c22d0 | ||
|
|
d427c52aac | ||
|
|
eb623a84d5 | ||
|
|
07290277ba | ||
|
|
743541218f | ||
|
|
94de0a7ce2 | ||
|
|
36e9fb292b | ||
|
|
2661e010d9 | ||
|
|
7687becfee | ||
|
|
1641f09dc9 | ||
|
|
1505673393 | ||
|
|
629e05b7b1 | ||
|
|
e98f6ae570 | ||
|
|
0b5bf0c098 | ||
|
|
1deefa48ee | ||
|
|
50c4aef873 | ||
|
|
cf42d31214 | ||
|
|
00caa1c0a0 | ||
|
|
93c8ba920a | ||
|
|
8702c04d39 | ||
|
|
c349892c5b | ||
|
|
3d4b8ce99b | ||
|
|
64fd87134f | ||
|
|
82bba44538 | ||
|
|
e6adbb0e42 | ||
|
|
11fc6be328 | ||
|
|
0ec8f5d283 | ||
|
|
b872df0f31 | ||
|
|
0add4af208 | ||
|
|
298cd9e065 | ||
|
|
b715d20385 | ||
|
|
9a00ccdacc | ||
|
|
e8d48e1f43 | ||
|
|
a2f8c9c75b | ||
|
|
5fb83e7f52 | ||
|
|
dd6bf568d1 | ||
|
|
00ee164cef | ||
|
|
448071b02d | ||
|
|
4dad9d0e37 | ||
|
|
3a2117c5d3 | ||
|
|
26a3f6ddc3 | ||
|
|
7741312673 | ||
|
|
954a1723f1 | ||
|
|
87285d94f7 | ||
|
|
d260d0c182 | ||
|
|
137eb40fab | ||
|
|
af440460e1 | ||
|
|
a5c8472a37 | ||
|
|
dfae37421d | ||
|
|
438a8d8b75 | ||
|
|
ac2034561d | ||
|
|
c42cd4233d | ||
|
|
5b2a73e3eb | ||
|
|
6f163a6ba5 | ||
|
|
cc94cc7d01 | ||
|
|
94934ae2cf | ||
|
|
e361f88501 | ||
|
|
708c042b61 | ||
|
|
600599f49e | ||
|
|
1fe7bbbbc4 | ||
|
|
f83d7a7cd1 | ||
|
|
7094047b3d | ||
|
|
11d3607688 | ||
|
|
fcae58d355 | ||
|
|
ef9ace9e65 | ||
|
|
22e4039133 | ||
|
|
4971670e56 | ||
|
|
e16cab6b9c | ||
|
|
a643c3dba6 | ||
|
|
51abf5b0a6 | ||
|
|
1cee6e309b | ||
|
|
0777a660bf | ||
|
|
5e0479e414 | ||
|
|
942c77816d | ||
|
|
8e260d5c40 | ||
|
|
7951eee8a3 | ||
|
|
be2f7d7a8a | ||
|
|
59c8e8b46e | ||
|
|
98c8b28bf3 | ||
|
|
7bb5bc01b7 | ||
|
|
1482c07ae4 | ||
|
|
adba84ae6a | ||
|
|
146e296826 | ||
|
|
28c10dba09 | ||
|
|
e646a0840d | ||
|
|
74ea6bf00a | ||
|
|
d7ad784809 | ||
|
|
642bd10dcc | ||
|
|
7c566c36f4 | ||
|
|
dbbe038939 | ||
|
|
e3430a916c | ||
|
|
ea1f041e11 | ||
|
|
0fe6d9f367 | ||
|
|
46e7359372 | ||
|
|
41cace9a96 | ||
|
|
4638331cb4 | ||
|
|
e339a7583c | ||
|
|
0b7570c9ee | ||
|
|
a85acfcfc5 | ||
|
|
3d4ccbec23 | ||
|
|
2f66ec60db | ||
|
|
f1cfe2b07b | ||
|
|
6160ca6e30 | ||
|
|
b621c3e4c4 | ||
|
|
64d2ae9ad4 | ||
|
|
39fc45b8d8 | ||
|
|
fd954adc81 | ||
|
|
8b379cbf56 | ||
|
|
59c0b04602 | ||
|
|
11b3cf3bfd | ||
|
|
9254f5a8a5 | ||
|
|
e5b68f4a3c | ||
|
|
95babc01e3 | ||
|
|
4dd792a49f | ||
|
|
207c50e500 | ||
|
|
763e34e861 | ||
|
|
b895a0c335 | ||
|
|
c5767eb545 | ||
|
|
94fb79c17f | ||
|
|
6856b02aa7 | ||
|
|
04f812c136 | ||
|
|
8783cf03b2 | ||
|
|
4e1156e083 | ||
|
|
1d6e1d416b | ||
|
|
fd02e5a07e | ||
|
|
937056fcaf | ||
|
|
41ed18684d | ||
|
|
96d4a22215 | ||
|
|
6e4ef508e8 | ||
|
|
4437d7f3c4 | ||
|
|
001570e941 | ||
|
|
28c41294bb | ||
|
|
82898da507 | ||
|
|
eabcdbf129 | ||
|
|
5ab11edad2 | ||
|
|
b57317bdc2 | ||
|
|
1f49f29183 | ||
|
|
638fbfabdc | ||
|
|
16de12a3ba | ||
|
|
1316578ba3 | ||
|
|
1926c50f09 | ||
|
|
b858a4a5d7 | ||
|
|
ec9741443b | ||
|
|
fe7b2a36ec | ||
|
|
2d88a726b7 | ||
|
|
a51edd3579 | ||
|
|
b7ede8f9ba | ||
|
|
15f36cc19d | ||
|
|
95edd970bc | ||
|
|
2c6285d4b3 | ||
|
|
1d1cdb5ea4 | ||
|
|
34bdef9c45 | ||
|
|
cad673f8cd | ||
|
|
7c446b222d | ||
|
|
1bd0f8fcf4 | ||
|
|
dd3c261ba2 | ||
|
|
70cc711ec1 | ||
|
|
485f2ee923 | ||
|
|
129be6e476 | ||
|
|
c08b64efb3 | ||
|
|
f4a0f55b13 | ||
|
|
39d32bcb5b | ||
|
|
3351fdbc74 | ||
|
|
7be1f018aa | ||
|
|
437daa368a | ||
|
|
3df09eacf2 | ||
|
|
483dd3435a | ||
|
|
2b0aa03380 | ||
|
|
fc7261b199 | ||
|
|
3200c50b9f | ||
|
|
862a8eab8d | ||
|
|
1bfcc92677 | ||
|
|
80a09b8f36 | ||
|
|
5f7ce4b868 | ||
|
|
412d97fa0c | ||
|
|
57bed98cf1 | ||
|
|
b1d8788506 | ||
|
|
1bd4900981 | ||
|
|
e6812f18a0 | ||
|
|
f604988181 | ||
|
|
150cdfd3ac | ||
|
|
f42b34d6b4 | ||
|
|
166b35bc6c | ||
|
|
121b74fa0c | ||
|
|
5451320350 | ||
|
|
fe45b29ef6 | ||
|
|
4e1aa8aa59 | ||
|
|
fa366eb7a8 | ||
|
|
e086a706ba | ||
|
|
53b8da8198 | ||
|
|
c2c5f71018 | ||
|
|
2bdc849c2b | ||
|
|
7cbe8f5843 | ||
|
|
810df61049 | ||
|
|
5c38101a9e | ||
|
|
b4236b9783 | ||
|
|
980c4699b0 | ||
|
|
463c7b5027 | ||
|
|
7c7230dd35 | ||
|
|
b915aafb5b | ||
|
|
8202ab83fa | ||
|
|
2fe6d14e56 | ||
|
|
7ee285342f | ||
|
|
6fe18ae0ab |
9
.gitignore
vendored
9
.gitignore
vendored
@@ -14,13 +14,17 @@ framework/assets/www/.DS_Store
|
||||
framework/assets/www/cordova-*.js
|
||||
framework/assets/www/phonegap-*.js
|
||||
framework/libs
|
||||
framework/javadoc-public
|
||||
framework/javadoc-private
|
||||
test/libs
|
||||
example
|
||||
./test
|
||||
test/bin
|
||||
test/assets/www/.tmp*
|
||||
test/assets/www/cordova.js
|
||||
test/cordova/plugins/org.apache.cordova.device/www/device.js
|
||||
test/cordova/plugins/org.apache.cordova.device/src/android/Device.java
|
||||
tmp/**
|
||||
bin/node_modules
|
||||
.metadata
|
||||
tmp/**/*
|
||||
Thumbs.db
|
||||
@@ -33,3 +37,6 @@ Desktop.ini
|
||||
# IntelliJ IDEA files
|
||||
*.iml
|
||||
.idea
|
||||
npm-debug.log
|
||||
/node_modules
|
||||
/framework/build
|
||||
|
||||
5
.travis.yml
Normal file
5
.travis.yml
Normal file
@@ -0,0 +1,5 @@
|
||||
language: android
|
||||
install: npm install
|
||||
script:
|
||||
- npm test
|
||||
- npm run test-build
|
||||
38
CONTRIBUTING.md
Normal file
38
CONTRIBUTING.md
Normal file
@@ -0,0 +1,38 @@
|
||||
<!--
|
||||
#
|
||||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance
|
||||
# with the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing,
|
||||
# software distributed under the License is distributed on an
|
||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
# KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
-->
|
||||
|
||||
# Contributing to Apache Cordova
|
||||
|
||||
Anyone can contribute to Cordova. And we need your contributions.
|
||||
|
||||
There are multiple ways to contribute: report bugs, improve the docs, and
|
||||
contribute code.
|
||||
|
||||
For instructions on this, start with the
|
||||
[contribution overview](http://cordova.apache.org/#contribute).
|
||||
|
||||
The details are explained there, but the important items are:
|
||||
- Sign and submit an Apache ICLA (Contributor License Agreement).
|
||||
- Have a Jira issue open that corresponds to your contribution.
|
||||
- Run the tests so your patch doesn't break existing functionality.
|
||||
|
||||
We look forward to your contributions!
|
||||
|
||||
87
LICENSE
87
LICENSE
@@ -199,4 +199,89 @@
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
limitations under the License.
|
||||
|
||||
ADDITIONAL LICENSES:
|
||||
|
||||
================================================================================
|
||||
bin/node_modules/q
|
||||
================================================================================
|
||||
|
||||
Copyright 2009–2012 Kristopher Michael Kowal. All rights reserved.
|
||||
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.
|
||||
|
||||
|
||||
================================================================================
|
||||
bin/node_modules/shelljs
|
||||
================================================================================
|
||||
|
||||
Copyright (c) 2012, Artur Adib <aadib@mozilla.com>
|
||||
All rights reserved.
|
||||
|
||||
You may use this project under the terms of the New BSD license as follows:
|
||||
|
||||
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 Artur Adib nor the
|
||||
names of the 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 ARTUR ADIB 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.
|
||||
|
||||
================================================================================
|
||||
bin/node_modules/shelljs
|
||||
================================================================================
|
||||
Copyright 2009, 2010, 2011 Isaac Z. Schlueter.
|
||||
All rights reserved.
|
||||
|
||||
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.
|
||||
|
||||
|
||||
8
NOTICE
8
NOTICE
@@ -1,5 +1,5 @@
|
||||
Apache Cordova
|
||||
Copyright 2012 The Apache Software Foundation
|
||||
Copyright 2014 The Apache Software Foundation
|
||||
|
||||
This product includes software developed at
|
||||
The Apache Software Foundation (http://www.apache.org)
|
||||
@@ -10,8 +10,8 @@ The Apache Software Foundation (http://www.apache.org)
|
||||
== in this case for the Android-specific code. ==
|
||||
=========================================================================
|
||||
|
||||
Android Code
|
||||
Copyright 2005-2008 The Android Open Source Project
|
||||
|
||||
This product includes software developed as part of
|
||||
The Android Open Source Project (http://source.android.com).
|
||||
|
||||
This software includes software developed at Square, Inc.
|
||||
Copyright (C) 2013 Square, Inc.
|
||||
|
||||
24
README.md
Executable file → Normal file
24
README.md
Executable file → Normal file
@@ -7,9 +7,9 @@
|
||||
# to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance
|
||||
# with the License. You may obtain a copy of the License at
|
||||
#
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing,
|
||||
# software distributed under the License is distributed on an
|
||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
@@ -23,27 +23,27 @@ Cordova Android
|
||||
|
||||
Cordova Android is an Android application library that allows for Cordova-based
|
||||
projects to be built for the Android Platform. Cordova based applications are,
|
||||
at the core, applications written with web technology: HTML, CSS and JavaScript.
|
||||
at the core, applications written with web technology: HTML, CSS and JavaScript.
|
||||
|
||||
[Apache Cordova](http://cordova.io) is a project at The Apache Software Foundation (ASF).
|
||||
[Apache Cordova](http://cordova.io) is a project of The Apache Software Foundation (ASF).
|
||||
|
||||
|
||||
Requires
|
||||
---
|
||||
|
||||
- Java JDK 1.5 or greater
|
||||
- Apache ANT 1.8.0 or greater
|
||||
- Apache Ant 1.8.0 or greater
|
||||
- Android SDK [http://developer.android.com](http://developer.android.com)
|
||||
|
||||
|
||||
|
||||
Cordova Android Developer Tools
|
||||
---
|
||||
|
||||
The Cordova developer tooling is split between general tooling and project level tooling.
|
||||
The Cordova developer tooling is split between general tooling and project level tooling.
|
||||
|
||||
General Commands
|
||||
|
||||
./bin/create [path package activity] ... create the ./example app or a cordova android project
|
||||
./bin/create [path package activity] ... creates the ./example app or a cordova android project
|
||||
./bin/check_reqs ....................... checks that your environment is set up for cordova-android development
|
||||
./bin/update [path] .................... updates an existing cordova-android project to the version of the framework
|
||||
|
||||
@@ -53,7 +53,7 @@ These commands live in a generated Cordova Android project. Any interactions wit
|
||||
|
||||
./cordova/clean ........................ cleans the project
|
||||
./cordova/build ........................ calls `clean` then compiles the project
|
||||
./cordova/log ........................ stream device or emulate logs to stdout
|
||||
./cordova/log ........................ streams device or emulator logs to STDOUT
|
||||
./cordova/run ........................ calls `build` then deploys to a connected Android device. If no Android device is detected, will launch an emulator and deploy to it.
|
||||
./cordova/version ...................... returns the cordova-android version of the current project
|
||||
|
||||
@@ -69,13 +69,13 @@ Importing a Cordova Android Project into Eclipse
|
||||
|
||||
Building without the Tooling
|
||||
---
|
||||
Note: The Developer Tools handle this. This is only to be done if the tooling fails, or if
|
||||
Note: The Developer Tools handle this. This is only to be done if the tooling fails, or if
|
||||
you are developing directly against the framework.
|
||||
|
||||
|
||||
To create your `cordova.jar` file, run in the framework directory:
|
||||
|
||||
android update project -p . -t android-17
|
||||
android update project -p . -t android-19
|
||||
ant jar
|
||||
|
||||
|
||||
@@ -84,7 +84,7 @@ Running Tests
|
||||
Please see details under test/README.md.
|
||||
|
||||
Further Reading
|
||||
---
|
||||
----
|
||||
|
||||
- [http://developer.android.com](http://developer.android.com)
|
||||
- [http://cordova.apache.org/](http://cordova.apache.org)
|
||||
|
||||
309
RELEASENOTES.md
Normal file
309
RELEASENOTES.md
Normal file
@@ -0,0 +1,309 @@
|
||||
<!--
|
||||
#
|
||||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance
|
||||
# with the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing,
|
||||
# software distributed under the License is distributed on an
|
||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
# KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
-->
|
||||
## Release Notes for Cordova (Android) ##
|
||||
|
||||
### Release 3.7.2 (May 2015) ###
|
||||
|
||||
* Removed Intent Functionality from Preferences - Preferences can no longer be set by intents
|
||||
|
||||
### Release 3.7.1 (January 2015) ###
|
||||
* CB-8411 Initialize plugins only after `createViews()` is called (regression in 3.7.0)
|
||||
|
||||
### Release 3.7.0 (January 2015) ###
|
||||
|
||||
* CB-8328 Allow plugins to handle certificate challenges (close #150)
|
||||
* CB-8201 Add support for auth dialogs into Cordova Android
|
||||
* CB-8017 Add support for `<input type=file>` for Lollipop
|
||||
* CB-8143 Loads of gradle improvements (try it with cordova/build --gradle)
|
||||
* CB-8329 Cancel outstanding ActivityResult requests when a new startActivityForResult occurs
|
||||
* CB-8026 Bumping up Android Version and setting it up to allow third-party cookies. This might change later.
|
||||
* CB-8210 Use PluginResult for various events from native so that content-security-policy <meta> can be used
|
||||
* CB-8168 Add support for `cordova/run --list` (closes #139)
|
||||
* CB-8176 Vastly better auto-detection of SDK & JDK locations
|
||||
* CB-8079 Use activity class package name, but fallback to application package name when looking for splash screen drawable
|
||||
* CB-8147 Have corodva/build warn about unrecognized flags rather than fail
|
||||
* CB-7881 Android tooling shouldn't lock application directory
|
||||
* CB-8112 Turn off mediaPlaybackRequiresUserGesture
|
||||
* CB-6153 Add a preference for controlling hardware button audio stream (DefaultVolumeStream)
|
||||
* CB-8031 Fix race condition that shows as ConcurrentModificationException
|
||||
* CB-7974 Cancel timeout timer if view is destroyed
|
||||
* CB-7940 Disable exec bridge if bridgeSecret is wrong
|
||||
* CB-7758 Allow content-url-hosted pages to access the bridge
|
||||
* CB-6511 Fixes build for android when app name contains unicode characters.
|
||||
* CB-7707 Added multipart PluginResult
|
||||
* CB-6837 Fix leaked window when hitting back button while alert being rendered
|
||||
* CB-7674 Move preference activation back into onCreate()
|
||||
* CB-7499 Support RTL text direction
|
||||
* CB-7330 Don't run check_reqs for bin/create.
|
||||
|
||||
### 3.6.4 (Sept 30, 2014) ###
|
||||
|
||||
* Set VERSION to 3.6.4 (via coho)
|
||||
* Update JS snapshot to version 3.6.4 (via coho)
|
||||
* CB-7634 Detect JAVA_HOME properly on Ubuntu
|
||||
* CB-7579 Fix run script's ability to use non-arch-specific APKs
|
||||
* CB-6511 Fixes build for android when app name contains unicode characters.
|
||||
* CB-7463: Adding licences. I don't know what the gradle syntax is for comments, that still needs to be done.
|
||||
* CB-7463: Looked at the Apache BigTop git, gradle uses C-style comments
|
||||
* CB-7460: Fixing bug with KitKat where the background colour would override the CSS colours on the application
|
||||
|
||||
### 3.6.0 (Sept 2014) ###
|
||||
|
||||
* Set VERSION to 3.6.0 (via coho)
|
||||
* CB-7410 fix the menu test
|
||||
* CB-7410 Fix the errorUrl test
|
||||
* CB-7410 Fix Basic Authentication test
|
||||
* CB-3445: Allow build and run scripts to select APK by architecture
|
||||
* CB-3445: Add environment variable 'BUILD_MULTIPLE_APKS' for splitting APKs based on architecture
|
||||
* CB-3445: Ensure that JAR files in libs directory are included
|
||||
* CB-7267 update RELEASENOTES for 3.5.1
|
||||
* CB-7410 clarify the title
|
||||
* CB-7385 update cordova.js for testing prior to branch/tag
|
||||
* CB-7410 add whitelist entries to get iframe/GoogleMaps working
|
||||
* CB-7291 propogate change in method signature to the native tests
|
||||
* CB-7291: Restrict meaning of "\*" in internal whitelist to just http and https
|
||||
* CB-7291: Only add file, content and data URLs to internal whitelist
|
||||
* CB-7291: Add defaults to external whitelist
|
||||
* CB-7291: Add external-launch-whitelist and use it for filtering intent launches
|
||||
* CB-3445: Read project.properties to configure gradle libraries
|
||||
* CB-7325 Fix error message in android_sdk_version.js when missing SDK on windows
|
||||
* CB-7335 Add a .gitignore to android project template
|
||||
* CB-7330 Fix dangling function call in last commit (broke gradle builds)
|
||||
* CB-7330 Don't run "android update" during creation
|
||||
* CB-3445 Add gradle support clean command (plus some code cleanup)
|
||||
* CB-7044 Fix typo in prev commit causing check_reqs to always fail.
|
||||
* CB-3445 Copy gradle wrapper in build instead of create
|
||||
* CB-3445 Add .gradle template files for "update" as well as "create"
|
||||
* CB-7044 Add JAVA_HOME when not set. Be stricter about ANDROID_HOME
|
||||
* CB-3445 Speed up gradle building (incremental builds go from 10s -> 1.5s for me)
|
||||
* CB-3445: android: Copy Gradle wrapper from Android SDK rather than bundling a JAR
|
||||
* CB-3445: Add which to checked-in node_modules
|
||||
* CB-3445: Add option to build and install with gradle
|
||||
* CB-3445: Add an initial set of Gradle build scripts
|
||||
* CB-7321 Don't require ant for create script
|
||||
* CB-7044, CB-7299 Fix up PATH problems when possible.
|
||||
* Change in test's AndroidManifest.xml needed for the test to run properly. Forgot the manifest.
|
||||
* Change in test's AndroidManifest.xml needed for the test to run properly
|
||||
* Adding tests related to 3.5.1
|
||||
* CB-7261 Fix setNativeToJsBridgeMode sometimes crashing when switching to ONLINE_EVENT
|
||||
* CB-7265 Fix crash when navigating to custom protocol (introduced in 3.5.1)
|
||||
* Filter out non-launchable intents
|
||||
* Handle unsupported protocol errors in webview better
|
||||
* CB-7238: I should have collapsed this, but Config.init() must go before the creation of CordovaWebView
|
||||
* CB-7238: Minor band-aid to get tests running again, this has to go away before 3.6.0 is released, since this is an API change.
|
||||
* Extend whitelist to handle URLs without // chars
|
||||
* CB-7172 Force window to have focus after resume
|
||||
* CB-7159 Set background color of webView as well as its parent
|
||||
* CB-7018 Fix setButtonPlumbedToJs never un-listening
|
||||
* Undeprecate some just-deprecated symbols in PluginManager.
|
||||
* @Deprecate methods of PluginManager that were never meant to be public
|
||||
* Move plugin instantiation and instance storing logic PluginEntry->PluginManager
|
||||
* Fix broken unit test due to missing Config.init() call
|
||||
* Update to check for Google Glass APIs
|
||||
* Fix for `android` not being in PATH check on Windows
|
||||
* Displaying error when regex does not match.
|
||||
* Fix broken compile due to previous commit :(
|
||||
* Tweak CordovaPlugin.initialize method to be less deprecated.
|
||||
* Un-deprecate CordovaActivity.init() - it's needed to tweak prefs in onCreate
|
||||
* Tweak log messages in CordovaBridge with bridgeSecret is wrong
|
||||
* Backport CordovaBridge from 4.0.x -> master
|
||||
* Update unit tests to not use most deprecated things (e.g. DroidGap)
|
||||
* Add non-String overloades for CordovaPreferences.set()
|
||||
* Make CordovaWebview resilient to init() not being called (for backwards-compatibility)
|
||||
* Add node_module licenses to LICENSE
|
||||
* Update cordova.js snapshot to work with bridge changes
|
||||
* Provide CordovaPlugin with CordovaPreferences. Add new Plugin.initialize()
|
||||
* Convert usages of Config.\* to use the non-static versions
|
||||
* Change getProperty -> prefs.get\* within CordovaActivity
|
||||
* Make CordovaUriHelper class package-private
|
||||
* Fix PluginManager.setPluginEntries not removing old entries
|
||||
* Move registration of App plugin from config.xml -> code
|
||||
* Make setWebViewClient an override instead of an overload. Delete Location-change JS->Native bridge mode (missed some of it).
|
||||
* CB-4404 Revert setting android:windowSoftInputMode to "adjustPan"
|
||||
* Refactor: Use ConfigXmlParser in activity. Adds CordovaWebView.init()
|
||||
* Deprecate some convenience methods on CordovaActivity
|
||||
* Fix CordovaPreferences not correctly parsing hex values (valueOf->decode)
|
||||
* Refactor: Move url-filter information into PluginEntry.
|
||||
* Don't re-parse config.xml in onResume.
|
||||
* Move handling of Fullscreen preference to CordovaActivity
|
||||
* Delete dead code from CordovaActivity
|
||||
* Update .classpath to make Eclipse happy (just re-orders one line)
|
||||
* Delete "CB-3064: The errorUrl is..." Log message left over from debugging presumably
|
||||
* Refactor Config into ConfigXmlParser, CordovaPreferences
|
||||
* Delete Location-change JS->Native bridge mode
|
||||
* CB-5988 Allow exec() only from file: or start-up URL's domain
|
||||
* CB-6761 Fix native->JS bridge ceasing to fire when page changes and online is set to false and the JS loads quickly
|
||||
* Update the errorurl to no longer use intents
|
||||
* This breaks running the JUnit tests, we'll bring it back soon
|
||||
* Refactoring the URI handling on Cordova, removing dead code
|
||||
* CB-7018 Clean up and deprecation of some button-related functions
|
||||
* CB-7017 Fix onload=true being set on all subsequent plugins
|
||||
* CB-5971: Fix package / project validation
|
||||
* CB-5971: Add unit tests to cordova-android
|
||||
* CB-5971: Factor out package/project name validation logic
|
||||
* Delete explicit activity.finish() in back button handling. No change in behaviour.
|
||||
* CB-5971: This would have been a good first bug, too bad
|
||||
* CB-4404: Changing where android:windowSoftInputMode is in the manifest so it works
|
||||
* Add documentation referencing other implementation.
|
||||
* CB-6851 Deprecate WebView.sendJavascript()
|
||||
* CB-6876 Show the correct executable name
|
||||
* CB-6876 Fix the "print usage"
|
||||
* Trivial spelling fix in comments when reading CordovaResourceApi
|
||||
* CB-6818: I want to remove this code, because Square didn't do their headers properly
|
||||
* CB-6860 Add activity_name and launcher_name to AndroidManifest.xml & strings.xml
|
||||
* Add a comment to custom_rules.xml saying why we move AndroidManifest.xml
|
||||
* Remove +x from README.md
|
||||
* CB-6784 Add missing licenses
|
||||
* CB-6784 Add license to CONTRIBUTING.md
|
||||
* Revert "defaults.xml: Add AndroidLaunchMode preference"
|
||||
* updated RELEASENOTES
|
||||
* CB-6315: Wrapping this so it runs on the UI thread
|
||||
* CB-6723 Update package name for Robotium
|
||||
* CB-6707 Update minSdkVersion to 10 consistently
|
||||
* CB-5652 make visible cordova version
|
||||
* Update JS snapshot to version 3.6.0-dev (via coho)
|
||||
* Update JS snapshot to version 3.6.0-dev (via coho)
|
||||
* Set VERSION to 3.6.0-dev (via coho)
|
||||
|
||||
### 3.5.1 (August 2014) ###
|
||||
|
||||
This was a security update to address CVE-2014-3500, CVE-2014-3501,
|
||||
and CVE-2014-3502. For more information, see
|
||||
http://cordova.apache.org/announcements/2014/08/04/android-351.html
|
||||
|
||||
* Filter out non-launchable intents
|
||||
* Handle unsupported protocol errors in webview better
|
||||
* Update the errorurl to no longer use intents
|
||||
* Refactoring the URI handling on Cordova, removing dead code
|
||||
|
||||
### 3.5.0 (May 2014) ###
|
||||
|
||||
* OkHttp has broken headers. Updating for ASF compliance.
|
||||
* Revert accidentally removed lines from NOTICE
|
||||
* CB-6552: added top level package.json
|
||||
* CB-6491 add CONTRIBUTING.md
|
||||
* CB-6543 Fix cordova/run failure when no custom_rules.xml available
|
||||
* defaults.xml: Add AndroidLaunchMode preference
|
||||
* Add JavaDoc for CordovaResourceApi
|
||||
* CB-6388: Handle binary data correctly in LOAD_URL bridge
|
||||
* Fix CB-6048: Set launchMode=singleTop so tapping app icon does not always restart app
|
||||
* Remove incorrect usage of AlertDialog.Builder.create
|
||||
* Catch uncaught exceptions in from plugins and turn them into error responses.
|
||||
* Add NOTICE file
|
||||
* CB-6047 Fix online sometimes getting in a bad state on page transitions.
|
||||
* Add another convenience overload for CordovaResourceApi.copyResource
|
||||
* Update framework's .classpath to what Eclipse wants it to be.
|
||||
* README.md: `android update` to `android-19`.
|
||||
* Fix NPE when POLLING bridge mode is used.
|
||||
* Updating NOTICE to include Square for OkHttp
|
||||
* CB-5398 Apply KitKat content URI fix to all content URIs
|
||||
* CB-5398 Work-around for KitKat content: URLs not rendering in <img> tags
|
||||
* CB-5908: add splascreen images to template
|
||||
* CB-5395: Make scheme and host (but not path) case-insensitive in whitelist
|
||||
* Ignore multiple onPageFinished() callbacks & onReceivedError due to stopLoading()
|
||||
* Removing addJavascriptInterface support from all Android versions lower than 4.2 due to security vu
|
||||
* CB-4984 Don't create on CordovaActivity name
|
||||
* CB-5917 Add a loadUrlIntoView overload that doesn't recreate plugins.
|
||||
* Use thread pool for load timeout.
|
||||
* CB-5715 For CLI, hide assets/www and res/xml/config.xml by default
|
||||
* CB-5793 ant builds: Rename AndroidManifest during -post-build to avoid Eclipse detecting ant-build/
|
||||
* CB-5889 Make update script find project name instead of using "null" for CordovaLib
|
||||
* CB-5889 Add a message in the update script about needing to import CordovaLib when using an IDE.
|
||||
|
||||
### 3.4.0 (Feb 2014) ###
|
||||
|
||||
43 commits from 10 authors. Highlights include:
|
||||
|
||||
* Removing addJavascriptInterface support from all Android versions lower than 4.2 due to security vulnerability
|
||||
* CB-5917 Add a loadUrlIntoView overload that doesn't recreate plugins.
|
||||
* CB-5889 Make update script find project name instead of using "null" for CordovaLib
|
||||
* CB-5889 Add a message in the update script about needing to import CordovaLib when using an IDE.
|
||||
* CB-5793 Don't clean before build and change output directory to ant-build to avoid conflicts with Eclipse.
|
||||
* CB-5803 Fix cordova/emulate on windows.
|
||||
* CB-5801 exec->spawn in build to make sure compile errors are shown.
|
||||
* CB-5799 Update version of OkHTTP to 1.3
|
||||
* CB-4910 Update CLI project template to point to config.xml at the root now that it's not in www/ by default.
|
||||
* CB-5504 Adding onDestroy to app plugin to deregister telephonyReceiver
|
||||
* CB-5715 Add Eclipse .project file to create template. For CLI projects, it adds refs for root www/ & config.xml and hides platform versions
|
||||
* CB-5447 Removed android:debuggable=“true” from project template.
|
||||
* CB-5714 Fix of android build when too big output stops build with error due to buffer overflow.
|
||||
* CB-5592 Set MIME type for openExternal when scheme is file:
|
||||
|
||||
### 3.3.0 (Dec 2013) ###
|
||||
|
||||
41 commits from 11 authors. Highlights include:
|
||||
|
||||
* CB-5481 Fix for Cordova trying to get config.xml from the wrong namespace
|
||||
* CB-5487 Enable Remote Debugging when your Android app is debuggable.
|
||||
* CB-5445 Adding onScrollChanged and the ScrollEvent object
|
||||
* CB-5422 Don't require JAVA_HOME to be defined
|
||||
* CB-5490 Add javadoc target to ant script
|
||||
* CB-5471 Deprecated DroidGap class
|
||||
* CB-5255 Prefer Google API targets over android-## targets when building.
|
||||
* CB-5232 Change create script to use Cordova as a Library Project instead of a .jar
|
||||
* CB-5302 Massive movement to get tests working again
|
||||
* CB-4996 Fix paths with spaces while launching on emulator and device
|
||||
* CB-5209 Cannot build Android app if project path contains spaces
|
||||
|
||||
|
||||
### 3.2.0 (Nov 2013) ###
|
||||
|
||||
27 commits from 7 authors. Highlights include:
|
||||
|
||||
* CB-5193 Fix Android WebSQL sometime throwing SECURITY_ERR.
|
||||
* CB-5191 Deprecate <url-filter>
|
||||
* Updating shelljs to 0.2.6. Copy now preserves mode bits.
|
||||
* CB-4872 Added android version scripts (android_sdk_version, etc)
|
||||
* CB-5117 Output confirmation message if check_reqs passes.
|
||||
* CB-5080 Find resources in a way that works with aapt's --rename-manifest-package
|
||||
* CB-4527 Don't delete .bat files even when on non-windows platform
|
||||
* CB-4892 Fix create script only escaping the first space instead of all spaces.
|
||||
|
||||
### 3.1.0 (Sept 2013) ###
|
||||
|
||||
55 commits from 9 authors. Highlights include:
|
||||
|
||||
* [CB-4817] Remove unused assets in project template.
|
||||
* Fail fast in create script if package name is not com.foo.bar.
|
||||
* [CB-4782] Convert ApplicationInfo.java -> appinfo.js
|
||||
* [CB-4766] Deprecated JSONUtils.java (moved into plugins)
|
||||
* [CB-4765] Deprecated ExifHelper.java (moved into plugins)
|
||||
* [CB-4764] Deprecated DirectoryManager.java (moved into plugins)
|
||||
* [CB-4763] Deprecated FileHelper.java (moved into plugins), Move getMimeType() into CordovaResourceApi.
|
||||
* [CB-4725] Add CordovaWebView.CORDOVA_VERSION constant
|
||||
* Incrementing version check for Android 4.3 API Level 18
|
||||
* [CB-3542] rewrote cli tooling scripts in node
|
||||
* Allow CordovaChromeClient subclasses access to CordovaInterface and CordovaWebView members
|
||||
* Refactor CordovaActivity.init so that subclasses can easily override factory methods for webview objects
|
||||
* [CB-4652] Allow default project template to be overridden on create
|
||||
* Tweak the online bridge to not send excess online events.
|
||||
* [CB-4495] Modify start-emulator script to exit immediately on a fatal emulator error.
|
||||
* Log WebView IOExceptions only when they are not 404s
|
||||
* Use a higher threshold for slow exec() warnings when debugger is attached.
|
||||
* Fix data URI decoding in CordovaResourceApi
|
||||
* [CB-3819] Made it easier to set SplashScreen delay.
|
||||
* [CB-4013] Fixed loadUrlTimeoutValue preference.
|
||||
* Upgrading project to Android 4.3
|
||||
* [CB-4198] bin/create script should be better at handling non-word characters in activity name. Patched windows script as well.
|
||||
* [CB-4198] bin/create should handle spaces in activity better.
|
||||
* [CB-4096] Implemented new unified whitelist for android
|
||||
* [CB-3384] Fix thread assertion when plugins remap URIs
|
||||
|
||||
29
bin/android_sdk_version
Executable file
29
bin/android_sdk_version
Executable file
@@ -0,0 +1,29 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
|
||||
var android_sdk_version = require('./lib/android_sdk_version');
|
||||
|
||||
android_sdk_version.run().done(null, function(err) {
|
||||
console.log(err);
|
||||
process.exit(2);
|
||||
});
|
||||
|
||||
|
||||
@@ -14,18 +14,13 @@
|
||||
:: KIND, either express or implied. See the License for the
|
||||
:: specific language governing permissions and limitations
|
||||
:: under the License.
|
||||
|
||||
@ECHO OFF
|
||||
IF NOT DEFINED JAVA_HOME GOTO MISSING
|
||||
FOR %%X in (java.exe ant.bat android.bat) do (
|
||||
SET FOUND=%%~$PATH:X
|
||||
IF NOT DEFINED FOUND GOTO MISSING
|
||||
SET script_path="%~dp0android_sdk_version"
|
||||
IF EXIST %script_path% (
|
||||
node "%script_path%" %*
|
||||
) ELSE (
|
||||
ECHO.
|
||||
ECHO ERROR: Could not find 'android_sdk_version' script in 'bin' folder, aborting...>&2
|
||||
EXIT /B 1
|
||||
)
|
||||
cscript %~dp0\lib\cordova.js %* //nologo
|
||||
GOTO END
|
||||
:MISSING
|
||||
ECHO Missing one of the following:
|
||||
ECHO JDK: http://java.oracle.com
|
||||
ECHO Android SDK: http://developer.android.com
|
||||
ECHO Apache ant: http://ant.apache.org
|
||||
EXIT /B 1
|
||||
:END
|
||||
@@ -1,34 +1,31 @@
|
||||
#! /bin/bash
|
||||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance
|
||||
# with the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing,
|
||||
# software distributed under the License is distributed on an
|
||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
# KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
ROOT="$( cd "$( dirname "$0" )/.." && pwd )"
|
||||
cmd=`android list target`
|
||||
if [[ $? != 0 ]]; then
|
||||
echo "The command `android` failed. Make sure you have the latest Android SDK installed, and the `android` command (inside the tools/ folder) added to your path."
|
||||
exit 2
|
||||
elif [[ ! $cmd =~ "android-17" ]]; then
|
||||
echo "Please install Android target 17 (the Android 4.2 SDK). Make sure you have the latest Android tools installed as well. Run `android` from your command-line to install/update any missing SDKs or tools."
|
||||
exit 2
|
||||
else
|
||||
cmd="android update project -p $ROOT -t android-17 1> /dev/null 2>&1"
|
||||
eval $cmd
|
||||
if [[ $? != 0 ]]; then
|
||||
echo "Error updating the Cordova library to work with your Android environment."
|
||||
exit 2
|
||||
fi
|
||||
fi
|
||||
#!/usr/bin/env node
|
||||
|
||||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
|
||||
var check_reqs = require('./lib/check_reqs');
|
||||
|
||||
check_reqs.run().done(
|
||||
function success() {
|
||||
console.log('Looks like your environment fully supports cordova-android development!');
|
||||
}, function fail(err) {
|
||||
console.log(err);
|
||||
process.exit(2);
|
||||
}
|
||||
);
|
||||
|
||||
@@ -16,11 +16,11 @@
|
||||
:: under the License.
|
||||
|
||||
@ECHO OFF
|
||||
SET full_path=%~dp0
|
||||
IF EXIST %full_path%check_reqs.js (
|
||||
cscript "%full_path%check_reqs.js" //nologo
|
||||
SET script_path="%~dp0check_reqs"
|
||||
IF EXIST %script_path% (
|
||||
node "%script_path%" %*
|
||||
) ELSE (
|
||||
ECHO.
|
||||
ECHO ERROR: Could not find 'check_reqs.js' in 'bin' folder, aborting...>&2
|
||||
ECHO ERROR: Could not find 'check_reqs' script in 'bin' folder, aborting...>&2
|
||||
EXIT /B 1
|
||||
)
|
||||
|
||||
@@ -1,81 +0,0 @@
|
||||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
var ROOT = WScript.ScriptFullName.split('\\bin\\check_reqs.js').join(''),
|
||||
shell = WScript.CreateObject("WScript.Shell"),
|
||||
fso = WScript.CreateObject('Scripting.FileSystemObject');
|
||||
|
||||
|
||||
// executes a command in the shell, returns stdout or stderr if error
|
||||
function exec_out(command) {
|
||||
var oExec=shell.Exec(command);
|
||||
var output = new String();
|
||||
while (oExec.Status == 0) {
|
||||
if (!oExec.StdOut.AtEndOfStream) {
|
||||
var line = oExec.StdOut.ReadAll();
|
||||
// XXX: Change to verbose mode
|
||||
// WScript.StdOut.WriteLine(line);
|
||||
output += line;
|
||||
}
|
||||
WScript.sleep(100);
|
||||
}
|
||||
//Check to make sure our scripts did not encounter an error
|
||||
if (!oExec.StdErr.AtEndOfStream) {
|
||||
var line = oExec.StdErr.ReadAll();
|
||||
return {'error' : true, 'output' : line};
|
||||
} else if (!oExec.StdOut.AtEndOfStream) {
|
||||
var line = oExec.StdOut.ReadAll();
|
||||
// XXX: Change to verbose mode
|
||||
// WScript.StdOut.WriteLine(line);
|
||||
output += line;
|
||||
}
|
||||
return {'error' : false, 'output' : output};
|
||||
}
|
||||
|
||||
// log to stdout or stderr
|
||||
function Log(msg, error) {
|
||||
if (error) {
|
||||
WScript.StdErr.WriteLine(msg);
|
||||
}
|
||||
else {
|
||||
WScript.StdOut.WriteLine(msg);
|
||||
}
|
||||
}
|
||||
|
||||
// checks that android requirements are met
|
||||
function check_requirements() {
|
||||
var result = exec_out('%comspec% /c android list target');
|
||||
if(result.error) {
|
||||
Log('The command `android` failed. Make sure you have the latest Android SDK installed, and the `android` command (inside the tools/ folder) added to your path. Output: ' + result.output, true);
|
||||
WScript.Quit(2);
|
||||
}
|
||||
else if(!result.output.match(/android[-]17/)) {
|
||||
Log('Please install Android target 17 (the Android 4.2 SDK). Make sure you have the latest Android tools installed as well. Run `android` from your command-line to install/update any missing SDKs or tools.', true);
|
||||
Log('Output : ' + result.output);
|
||||
WScript.Quit(2);
|
||||
}
|
||||
else {
|
||||
var cmd = '%comspec% /c android update project -p ' + ROOT + '\\framework -t android-17';
|
||||
result = exec_out(cmd);
|
||||
if(result.error) {
|
||||
Log('Error updating the Cordova library to work with your Android environment. Command run: "' + cmd + '", output: ' + result.output, true);
|
||||
WScript.Quit(2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
check_requirements();
|
||||
175
bin/create
175
bin/create
@@ -1,153 +1,36 @@
|
||||
#! /bin/bash
|
||||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance
|
||||
# with the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing,
|
||||
# software distributed under the License is distributed on an
|
||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
# KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
# create a cordova/android project
|
||||
#
|
||||
# USAGE
|
||||
# ./create [path package activity]
|
||||
#
|
||||
set -e
|
||||
#!/usr/bin/env node
|
||||
|
||||
if [ -z "$1" ] || [ "$1" == "-h" ]
|
||||
then
|
||||
echo "Usage: $0 <path_to_new_project> <package_name> <project_name>"
|
||||
echo "Make sure the Android SDK tools folder is in your PATH!"
|
||||
echo " <path_to_new_project>: Path to your new Cordova iOS project"
|
||||
echo " <package_name>: Package name, following reverse-domain style convention"
|
||||
echo " <project_name>: Project name"
|
||||
exit 0
|
||||
fi
|
||||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
BUILD_PATH="$( cd "$( dirname "$0" )/.." && pwd )"
|
||||
VERSION=$(cat "$BUILD_PATH"/VERSION)
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
PROJECT_PATH="${1:-'./example'}"
|
||||
PACKAGE=${2:-"org.apache.cordova.example"}
|
||||
ACTIVITY=${3:-"cordovaExample"}
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
var path = require('path');
|
||||
var create = require('./lib/create');
|
||||
var args = require('./lib/simpleargs').getArgs(process.argv);
|
||||
|
||||
# clobber any existing example
|
||||
if [ -d "$PROJECT_PATH" ]
|
||||
then
|
||||
echo "Project already exists! Delete and recreate"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
function createAppInfoJar {
|
||||
pushd "$BUILD_PATH"/bin/templates/cordova/ApplicationInfo > /dev/null
|
||||
javac ApplicationInfo.java
|
||||
jar -cfe ../appinfo.jar ApplicationInfo ApplicationInfo.class
|
||||
popd > /dev/null
|
||||
if (args['--help'] || args._.length === 0) {
|
||||
console.log('Usage: ' + path.relative(process.cwd(), path.join(__dirname, 'create')) + ' <path_to_new_project> <package_name> <project_name> [<template_path>] [--shared]');
|
||||
console.log(' <path_to_new_project>: Path to your new Cordova Android project');
|
||||
console.log(' <package_name>: Package name, following reverse-domain style convention');
|
||||
console.log(' <project_name>: Project name');
|
||||
console.log(' <template_path>: Path to a custom application template to use');
|
||||
console.log(' --shared will use the CordovaLib project directly instead of making a copy.');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
function on_error {
|
||||
echo "An unexpected error occurred: $previous_command exited with $?"
|
||||
echo "Deleting project..."
|
||||
[ -d "$PROJECT_PATH" ] && rm -rf "$PROJECT_PATH"
|
||||
exit 1
|
||||
}
|
||||
|
||||
function replace {
|
||||
local pattern=$1
|
||||
local filename=$2
|
||||
# Mac OS X requires -i argument
|
||||
if [[ "$OSTYPE" =~ "darwin" ]]
|
||||
then
|
||||
/usr/bin/sed -i '' -e $pattern "$filename"
|
||||
elif [[ "$OSTYPE" =~ "linux" ]]
|
||||
then
|
||||
/bin/sed -i -e $pattern "$filename"
|
||||
fi
|
||||
}
|
||||
|
||||
# we do not want the script to silently fail
|
||||
trap 'previous_command=$this_command; this_command=$BASH_COMMAND' DEBUG
|
||||
trap on_error ERR
|
||||
|
||||
ANDROID_BIN="${ANDROID_BIN:=$( which android )}"
|
||||
PACKAGE_AS_PATH=$(echo $PACKAGE | sed 's/\./\//g')
|
||||
ACTIVITY_PATH="$PROJECT_PATH"/src/$PACKAGE_AS_PATH/$ACTIVITY.java
|
||||
MANIFEST_PATH="$PROJECT_PATH"/AndroidManifest.xml
|
||||
|
||||
TARGET=$("$ANDROID_BIN" list targets -c | grep '^android-' | tail -1 )
|
||||
API_LEVEL=${TARGET##android-}
|
||||
|
||||
# check that build targets exist
|
||||
if [ -z "$TARGET" ] || [ -z "$API_LEVEL" ]
|
||||
then
|
||||
echo "No Android Targets are installed. Please install at least one via the android SDK"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# if this a distribution release no need to build a jar
|
||||
if [ ! -e "$BUILD_PATH"/cordova-$VERSION.jar ] && [ -d "$BUILD_PATH"/framework ]
|
||||
then
|
||||
# update the cordova-android framework for the desired target
|
||||
"$ANDROID_BIN" update project --target $TARGET --path "$BUILD_PATH"/framework &> /dev/null
|
||||
|
||||
# compile cordova.js and cordova.jar
|
||||
pushd "$BUILD_PATH"/framework > /dev/null
|
||||
ant jar > /dev/null
|
||||
popd > /dev/null
|
||||
fi
|
||||
|
||||
# create new android project
|
||||
"$ANDROID_BIN" create project --target $TARGET --path "$PROJECT_PATH" --package $PACKAGE --activity $ACTIVITY &> /dev/null
|
||||
|
||||
# copy project template
|
||||
cp -r "$BUILD_PATH"/bin/templates/project/assets "$PROJECT_PATH"
|
||||
cp -r "$BUILD_PATH"/bin/templates/project/res "$PROJECT_PATH"
|
||||
|
||||
# copy cordova.js, cordova.jar and res/xml
|
||||
if [ -d "$BUILD_PATH"/framework ]
|
||||
then
|
||||
cp -r "$BUILD_PATH"/framework/res/xml "$PROJECT_PATH"/res
|
||||
cp "$BUILD_PATH"/framework/assets/www/cordova.js "$PROJECT_PATH"/assets/www/cordova.js
|
||||
cp "$BUILD_PATH"/framework/cordova-$VERSION.jar "$PROJECT_PATH"/libs/cordova-$VERSION.jar
|
||||
else
|
||||
cp -r "$BUILD_PATH"/xml "$PROJECT_PATH"/res/xml
|
||||
cp "$BUILD_PATH"/cordova.js "$PROJECT_PATH"/assets/www/cordova.js
|
||||
cp "$BUILD_PATH"/cordova-$VERSION.jar "$PROJECT_PATH"/libs/cordova-$VERSION.jar
|
||||
fi
|
||||
|
||||
# interpolate the activity name and package
|
||||
cp "$BUILD_PATH"/bin/templates/project/Activity.java "$ACTIVITY_PATH"
|
||||
replace "s/__ACTIVITY__/${ACTIVITY}/g" "$ACTIVITY_PATH"
|
||||
replace "s/__ID__/${PACKAGE}/g" "$ACTIVITY_PATH"
|
||||
|
||||
cp "$BUILD_PATH"/bin/templates/project/AndroidManifest.xml "$MANIFEST_PATH"
|
||||
replace "s/__ACTIVITY__/${ACTIVITY}/g" "$MANIFEST_PATH"
|
||||
replace "s/__PACKAGE__/${PACKAGE}/g" "$MANIFEST_PATH"
|
||||
replace "s/__APILEVEL__/${API_LEVEL}/g" "$MANIFEST_PATH"
|
||||
|
||||
# creating cordova folder and copying run/build/log/launch scripts
|
||||
mkdir "$PROJECT_PATH"/cordova
|
||||
mkdir "$PROJECT_PATH"/cordova/lib
|
||||
createAppInfoJar
|
||||
cp "$BUILD_PATH"/bin/templates/cordova/appinfo.jar "$PROJECT_PATH"/cordova/appinfo.jar
|
||||
cp "$BUILD_PATH"/bin/templates/cordova/build "$PROJECT_PATH"/cordova/build
|
||||
cp "$BUILD_PATH"/bin/templates/cordova/clean "$PROJECT_PATH"/cordova/clean
|
||||
cp "$BUILD_PATH"/bin/templates/cordova/log "$PROJECT_PATH"/cordova/log
|
||||
cp "$BUILD_PATH"/bin/templates/cordova/run "$PROJECT_PATH"/cordova/run
|
||||
cp "$BUILD_PATH"/bin/templates/cordova/version "$PROJECT_PATH"/cordova/version
|
||||
cp "$BUILD_PATH"/bin/templates/cordova/lib/install-device "$PROJECT_PATH"/cordova/lib/install-device
|
||||
cp "$BUILD_PATH"/bin/templates/cordova/lib/install-emulator "$PROJECT_PATH"/cordova/lib/install-emulator
|
||||
cp "$BUILD_PATH"/bin/templates/cordova/lib/list-devices "$PROJECT_PATH"/cordova/lib/list-devices
|
||||
cp "$BUILD_PATH"/bin/templates/cordova/lib/list-emulator-images "$PROJECT_PATH"/cordova/lib/list-emulator-images
|
||||
cp "$BUILD_PATH"/bin/templates/cordova/lib/list-started-emulators "$PROJECT_PATH"/cordova/lib/list-started-emulators
|
||||
cp "$BUILD_PATH"/bin/templates/cordova/lib/start-emulator "$PROJECT_PATH"/cordova/lib/start-emulator
|
||||
create.createProject(args._[0], args._[1], args._[2], args._[3], args['--shared'], args['--cli']).done();
|
||||
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
@ECHO OFF
|
||||
GOTO BEGIN
|
||||
:: Licensed to the Apache Software Foundation (ASF) under one
|
||||
:: or more contributor license agreements. See the NOTICE file
|
||||
:: distributed with this work for additional information
|
||||
@@ -17,38 +15,12 @@ GOTO BEGIN
|
||||
:: specific language governing permissions and limitations
|
||||
:: under the License.
|
||||
|
||||
:BEGIN
|
||||
IF NOT DEFINED JAVA_HOME GOTO MISSING_JAVA_HOME
|
||||
|
||||
FOR %%X in (java.exe javac.exe ant.bat android.bat) do (
|
||||
IF [%%~$PATH:X]==[] (
|
||||
ECHO Cannot locate %%X using the PATH environment variable.
|
||||
ECHO Retry after adding directory containing %%X to the PATH variable.
|
||||
ECHO Remember to open a new command window after updating the PATH variable.
|
||||
IF "%%X"=="java.exe" GOTO GET_JAVA
|
||||
IF "%%X"=="javac.exe" GOTO GET_JAVA
|
||||
IF "%%X"=="ant.bat" GOTO GET_ANT
|
||||
IF "%%X"=="android.bat" GOTO GET_ANDROID
|
||||
GOTO ERROR
|
||||
)
|
||||
)
|
||||
cscript "%~dp0\create.js" %* //nologo
|
||||
GOTO END
|
||||
:MISSING_JAVA_HOME
|
||||
ECHO The JAVA_HOME environment variable is not set.
|
||||
ECHO Set JAVA_HOME to an existing JRE directory.
|
||||
ECHO Remember to also add JAVA_HOME to the PATH variable.
|
||||
ECHO After updating system variables, open a new command window and retry.
|
||||
GOTO ERROR
|
||||
:GET_JAVA
|
||||
ECHO Visit http://java.oracle.com if you need to install Java (JDK).
|
||||
GOTO ERROR
|
||||
:GET_ANT
|
||||
ECHO Visit http://ant.apache.org if you need to install Apache Ant.
|
||||
GOTO ERROR
|
||||
:GET_ANDROID
|
||||
ECHO Visit http://developer.android.com if you need to install the Android SDK.
|
||||
GOTO ERROR
|
||||
:ERROR
|
||||
EXIT /B 1
|
||||
:END
|
||||
@ECHO OFF
|
||||
SET script_path="%~dp0create"
|
||||
IF EXIST %script_path% (
|
||||
node %script_path% %*
|
||||
) ELSE (
|
||||
ECHO.
|
||||
ECHO ERROR: Could not find 'create' script in 'bin' folder, aborting...>&2
|
||||
EXIT /B 1
|
||||
)
|
||||
210
bin/create.js
210
bin/create.js
@@ -1,210 +0,0 @@
|
||||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
* create a cordova/android project
|
||||
*
|
||||
* USAGE
|
||||
* ./create [path package activity]
|
||||
*/
|
||||
|
||||
var args = WScript.Arguments, PROJECT_PATH="example",
|
||||
PACKAGE="org.apache.cordova.example", ACTIVITY="cordovaExample",
|
||||
shell=WScript.CreateObject("WScript.Shell"),
|
||||
fso = WScript.CreateObject('Scripting.FileSystemObject');
|
||||
|
||||
function Usage() {
|
||||
Log("Usage: create PathTONewProject [ PackageName AppName ]");
|
||||
Log(" PathTONewProject : The path to where you wish to create the project");
|
||||
Log(" PackageName : The package for the project (default is org.apache.cordova.example)")
|
||||
Log(" AppName : The name of the application/activity (default is cordovaExample)");
|
||||
Log("examples:");
|
||||
Log(" create C:\\Users\\anonymous\\Desktop\\MyProject");
|
||||
Log(" create C:\\Users\\anonymous\\Desktop\\MyProject io.Cordova.Example AnApp");
|
||||
}
|
||||
|
||||
// logs messaged to stdout and stderr
|
||||
function Log(msg, error) {
|
||||
if (error) {
|
||||
WScript.StdErr.WriteLine(msg);
|
||||
}
|
||||
else {
|
||||
WScript.StdOut.WriteLine(msg);
|
||||
}
|
||||
}
|
||||
|
||||
function read(filename) {
|
||||
var fso=WScript.CreateObject("Scripting.FileSystemObject");
|
||||
var f=fso.OpenTextFile(filename, 1);
|
||||
var s=f.ReadAll();
|
||||
f.Close();
|
||||
return s;
|
||||
}
|
||||
|
||||
function checkTargets(targets) {
|
||||
if(!targets) {
|
||||
Log("You do not have any android targets setup. Please create at least one target with the `android` command", true);
|
||||
WScript.Quit(69);
|
||||
}
|
||||
}
|
||||
|
||||
function setTarget() {
|
||||
var targets = shell.Exec('android.bat list targets').StdOut.ReadAll().match(/id:\s\d+/g);
|
||||
checkTargets(targets);
|
||||
return targets[targets.length - 1].replace(/id: /, ""); // TODO: give users the option to set their target
|
||||
}
|
||||
function setApiLevel() {
|
||||
var targets = shell.Exec('android.bat list targets').StdOut.ReadAll().match(/API level:\s\d+/g);
|
||||
checkTargets(targets);
|
||||
return targets[targets.length - 1].replace(/API level: /, "");
|
||||
}
|
||||
function write(filename, contents) {
|
||||
var fso=WScript.CreateObject("Scripting.FileSystemObject");
|
||||
var f=fso.OpenTextFile(filename, 2, true);
|
||||
f.Write(contents);
|
||||
f.Close();
|
||||
}
|
||||
function replaceInFile(filename, regexp, replacement) {
|
||||
write(filename, read(filename).replace(regexp, replacement));
|
||||
}
|
||||
function exec(command) {
|
||||
var oShell=shell.Exec(command);
|
||||
while (oShell.Status == 0) {
|
||||
if(!oShell.StdOut.AtEndOfStream) {
|
||||
var line = oShell.StdOut.ReadLine();
|
||||
// XXX: Change to verbose mode
|
||||
// WScript.StdOut.WriteLine(line);
|
||||
}
|
||||
WScript.sleep(100);
|
||||
}
|
||||
}
|
||||
|
||||
function createAppInfoJar() {
|
||||
if(!fso.FileExists(ROOT+"\\bin\\templates\\cordova\\appinfo.jar")) {
|
||||
Log("Creating appinfo.jar...");
|
||||
var cur = shell.CurrentDirectory;
|
||||
shell.CurrentDirectory = ROOT+"\\bin\\templates\\cordova\\ApplicationInfo";
|
||||
exec("javac ApplicationInfo.java");
|
||||
exec("jar -cfe ..\\appinfo.jar ApplicationInfo ApplicationInfo.class");
|
||||
shell.CurrentDirectory = cur;
|
||||
}
|
||||
}
|
||||
|
||||
// working dir
|
||||
var ROOT = WScript.ScriptFullName.split('\\bin\\create.js').join('');
|
||||
if (args.Count() > 0) {
|
||||
// support help flags
|
||||
if (args(0) == "--help" || args(0) == "/?" ||
|
||||
args(0) == "help" || args(0) == "-help" || args(0) == "/help" || args(0) == "-h") {
|
||||
Usage();
|
||||
WScript.Quit(2);
|
||||
}
|
||||
|
||||
PROJECT_PATH=args(0);
|
||||
if (args.Count() > 1) {
|
||||
PACKAGE = args(1);
|
||||
}
|
||||
if (args.Count() > 2) {
|
||||
ACTIVITY = args(2);
|
||||
}
|
||||
}
|
||||
else {
|
||||
Log("Error : No project path provided.");
|
||||
Usage();
|
||||
WScript.Quit(2);
|
||||
}
|
||||
|
||||
if(fso.FolderExists(PROJECT_PATH)) {
|
||||
Log("Project path already exists!", true);
|
||||
WScript.Quit(2);
|
||||
}
|
||||
|
||||
var PACKAGE_AS_PATH=PACKAGE.replace(/\./g, '\\');
|
||||
var ACTIVITY_DIR=PROJECT_PATH + '\\src\\' + PACKAGE_AS_PATH;
|
||||
var ACTIVITY_PATH=ACTIVITY_DIR+'\\'+ACTIVITY+'.java';
|
||||
var MANIFEST_PATH=PROJECT_PATH+'\\AndroidManifest.xml';
|
||||
var TARGET=setTarget();
|
||||
var API_LEVEL=setApiLevel();
|
||||
var VERSION=read(ROOT+'\\VERSION').replace(/\r\n/,'').replace(/\n/,'');
|
||||
// create the project
|
||||
Log("Creating new android project...");
|
||||
exec('android.bat create project --target "'+TARGET+'" --path "'+PROJECT_PATH+'" --package "'+PACKAGE+'" --activity "'+ACTIVITY+'"');
|
||||
|
||||
// build from source. distro should have these files
|
||||
if (!fso.FileExists(ROOT+'\\cordova-'+VERSION+'.jar') &&
|
||||
!fso.FileExists(ROOT+'\\cordova.js')) {
|
||||
Log("Building jar and js files...");
|
||||
// update the cordova framework project to a target that exists on this machine
|
||||
exec('android.bat update project --target "'+TARGET+'" --path "'+ROOT+'\\framework"');
|
||||
exec('ant.bat -f "'+ ROOT +'\\framework\\build.xml" jar');
|
||||
}
|
||||
|
||||
// copy in the project template
|
||||
Log("Copying template files...");
|
||||
exec('%comspec% /c xcopy "'+ ROOT + '\\bin\\templates\\project\\res" "'+PROJECT_PATH+'\\res\\" /E /Y');
|
||||
exec('%comspec% /c xcopy "'+ ROOT + '\\bin\\templates\\project\\assets" "'+PROJECT_PATH+'\\assets\\" /E /Y');
|
||||
exec('%comspec% /c copy "'+ROOT+'\\bin\\templates\\project\\AndroidManifest.xml" "' + PROJECT_PATH + '\\AndroidManifest.xml" /Y');
|
||||
exec('%comspec% /c mkdir "' + ACTIVITY_DIR + '"');
|
||||
exec('%comspec% /c copy "' + ROOT + '"\\bin\\templates\\project\\Activity.java "' + ACTIVITY_PATH + '" /Y');
|
||||
|
||||
// check if we have the source or the distro files
|
||||
Log("Copying js, jar & config.xml files...");
|
||||
if(fso.FolderExists(ROOT + '\\framework')) {
|
||||
exec('%comspec% /c copy "'+ROOT+'\\framework\\assets\\www\\cordova.js" "'+PROJECT_PATH+'\\assets\\www\\cordova.js" /Y');
|
||||
exec('%comspec% /c copy "'+ROOT+'\\framework\\cordova-'+VERSION+'.jar" "'+PROJECT_PATH+'\\libs\\cordova-'+VERSION+'.jar" /Y');
|
||||
fso.CreateFolder(PROJECT_PATH + '\\res\\xml');
|
||||
exec('%comspec% /c copy "'+ROOT+'\\framework\\res\\xml\\config.xml" "' + PROJECT_PATH + '\\res\\xml\\config.xml" /Y');
|
||||
} else {
|
||||
// copy in cordova.js
|
||||
exec('%comspec% /c copy "'+ROOT+'\\cordova.js" "'+PROJECT_PATH+'\\assets\\www\\cordova.js" /Y');
|
||||
// copy in cordova.jar
|
||||
exec('%comspec% /c copy "'+ROOT+'\\cordova-'+VERSION+'.jar" "'+PROJECT_PATH+'\\libs\\cordova-'+VERSION+'.jar" /Y');
|
||||
// copy in xml
|
||||
fso.CreateFolder(PROJECT_PATH + '\\res\\xml');
|
||||
exec('%comspec% /c copy "'+ROOT+'\\xml\\config.xml" "' + PROJECT_PATH + '\\res\\xml\\config.xml" /Y');
|
||||
}
|
||||
|
||||
// copy cordova scripts
|
||||
fso.CreateFolder(PROJECT_PATH + '\\cordova');
|
||||
fso.CreateFolder(PROJECT_PATH + '\\cordova\\lib');
|
||||
createAppInfoJar();
|
||||
Log("Copying cordova command tools...");
|
||||
exec('%comspec% /c copy "'+ROOT+'\\bin\\templates\\cordova\\appinfo.jar" "' + PROJECT_PATH + '\\cordova\\appinfo.jar" /Y');
|
||||
exec('%comspec% /c copy "'+ROOT+'\\bin\\templates\\cordova\\lib\\cordova.js" "' + PROJECT_PATH + '\\cordova\\lib\\cordova.js" /Y');
|
||||
exec('%comspec% /c copy "'+ROOT+'\\bin\\templates\\cordova\\lib\\install-device.bat" "' + PROJECT_PATH + '\\cordova\\lib\\install-device.bat" /Y');
|
||||
exec('%comspec% /c copy "'+ROOT+'\\bin\\templates\\cordova\\lib\\install-emulator.bat" "' + PROJECT_PATH + '\\cordova\\lib\\install-emulator.bat" /Y');
|
||||
exec('%comspec% /c copy "'+ROOT+'\\bin\\templates\\cordova\\lib\\list-emulator-images.bat" "' + PROJECT_PATH + '\\cordova\\lib\\list-emulator-images.bat" /Y');
|
||||
exec('%comspec% /c copy "'+ROOT+'\\bin\\templates\\cordova\\lib\\list-devices.bat" "' + PROJECT_PATH + '\\cordova\\lib\\list-devices.bat" /Y');
|
||||
exec('%comspec% /c copy "'+ROOT+'\\bin\\templates\\cordova\\lib\\list-started-emulators.bat" "' + PROJECT_PATH + '\\cordova\\lib\\list-started-emulators.bat" /Y');
|
||||
exec('%comspec% /c copy "'+ROOT+'\\bin\\templates\\cordova\\lib\\start-emulator.bat" "' + PROJECT_PATH + '\\cordova\\lib\\start-emulator.bat" /Y');
|
||||
exec('%comspec% /c copy "'+ROOT+'\\bin\\templates\\cordova\\cordova.bat" "' + PROJECT_PATH + '\\cordova\\cordova.bat" /Y');
|
||||
exec('%comspec% /c copy "'+ROOT+'\\bin\\templates\\cordova\\clean.bat" "' + PROJECT_PATH + '\\cordova\\clean.bat" /Y');
|
||||
exec('%comspec% /c copy "'+ROOT+'\\bin\\templates\\cordova\\build.bat" "' + PROJECT_PATH + '\\cordova\\build.bat" /Y');
|
||||
exec('%comspec% /c copy "'+ROOT+'\\bin\\templates\\cordova\\log.bat" "' + PROJECT_PATH + '\\cordova\\log.bat" /Y');
|
||||
exec('%comspec% /c copy "'+ROOT+'\\bin\\templates\\cordova\\run.bat" "' + PROJECT_PATH + '\\cordova\\run.bat" /Y');
|
||||
exec('%comspec% /c copy "'+ROOT+'\\bin\\templates\\cordova\\version.bat" "' + PROJECT_PATH + '\\cordova\\version.bat" /Y');
|
||||
|
||||
// interpolate the activity name and package
|
||||
Log("Updating AndroidManifest.xml and Main Activity...");
|
||||
replaceInFile(ACTIVITY_PATH, /__ACTIVITY__/, ACTIVITY);
|
||||
replaceInFile(ACTIVITY_PATH, /__ID__/, PACKAGE);
|
||||
|
||||
replaceInFile(MANIFEST_PATH, /__ACTIVITY__/, ACTIVITY);
|
||||
replaceInFile(MANIFEST_PATH, /__PACKAGE__/, PACKAGE);
|
||||
replaceInFile(MANIFEST_PATH, /__APILEVEL__/, API_LEVEL);
|
||||
@@ -1,98 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
-->
|
||||
|
||||
<project name="cordova" default="create" basedir="../">
|
||||
|
||||
<property name="project.path" value="${basedir}/example"/>
|
||||
<property name="package" value="org.apache.cordova.example"/>
|
||||
<property name="activity" value="cordovaExample"/>
|
||||
|
||||
<target name="create">
|
||||
|
||||
<!-- this stuff is seriously stupid -->
|
||||
<echo file="tmp/package.tmp">package-as-path=${package}</echo>
|
||||
<replace file="tmp/package.tmp" token="." value="\\" />
|
||||
<property file="tmp/package.tmp" />
|
||||
|
||||
<property name="activity.path" value="${project.path}/src/${package-as-path}/${activity}.java" />
|
||||
<property name="manifest.path" value="${project.path}/AndroidManifest.xml" />
|
||||
|
||||
<!-- get the highest target on this machine -->
|
||||
<!-- this stuff is also seriously stupid -->
|
||||
<exec executable="cmd" osfamily="windows" output="tmp/target.list.tmp">
|
||||
<arg line="/c android.bat list targets"/>
|
||||
</exec>
|
||||
<exec executable="android" osfamily="mac" output="tmp/target.list.tmp">
|
||||
<arg line="list targets"/>
|
||||
</exec>
|
||||
<replaceregexp file="tmp/target.list.tmp" match=".*id:\s([0-9]).*" replace="target=\1" flags="s" />
|
||||
<property file="tmp/target.list.tmp" />
|
||||
|
||||
<!-- var VERSION=read('VERSION').replace(/\r\n/,'').replace(/\n/,''); -->
|
||||
<copy file="VERSION" tofile="tmp/VERSION.tmp" overwrite="true" />
|
||||
<replaceregexp file="tmp/VERSION.tmp" match="^" replace="version=" />
|
||||
<replaceregexp file="tmp/VERSION.tmp" match="\r\n" replace="" />
|
||||
<property file="tmp/VERSION.tmp" />
|
||||
|
||||
<!-- clobber any existing example -->
|
||||
|
||||
<!-- create the project -->
|
||||
<exec executable="cmd" osfamily="windows">
|
||||
<arg line="/c android.bat create project --target ${target} --path ${project.path} --package ${package} --activity ${activity}"/>
|
||||
</exec>
|
||||
<exec executable="android" osfamily="mac">
|
||||
<arg line="create project --target ${target} --path ${project.path} --package ${package} --activity ${activity}"/>
|
||||
</exec>
|
||||
|
||||
<!-- update the framework dir -->
|
||||
<exec executable="cmd" osfamily="windows">
|
||||
<arg line="/c android.bat update project --target ${target} --path ${basedir}/framework"/>
|
||||
</exec>
|
||||
<exec executable="android" osfamily="mac">
|
||||
<arg line="update project --target ${target} --path ${basedir}/framework"/>
|
||||
</exec>
|
||||
|
||||
<!-- compile cordova.js and cordova.jar -->
|
||||
<!-- // if you see an error about "Unable to resolve target" then you may need to
|
||||
// update your android tools or install an additional Android platform version -->
|
||||
<ant antfile="${basedir}/framework/build.xml" useNativeBasedir="true" inheritAll="false" />
|
||||
|
||||
<!-- copy in the project template -->
|
||||
<copy todir="${project.path}" overwrite="true">
|
||||
<fileset dir="${basedir}/bin/templates/project"/>
|
||||
</copy>
|
||||
|
||||
<!-- copy in cordova.js -->
|
||||
<copy file="${basedir}/framework/assets/www/cordova-${version}.js" todir="${project.path}/assets/www/" />
|
||||
|
||||
<!-- copy in cordova.jar -->
|
||||
<copy file="${basedir}/framework/cordova-${version}.jar" todir="${project.path}/libs/" />
|
||||
|
||||
<!-- copy in default activity -->
|
||||
<copy file="${basedir}/bin/templates/Activity.java" tofile="${activity.path}" overwrite="true" />
|
||||
|
||||
<!-- interpolate the activity name and package -->
|
||||
<replaceregexp file="${activity.path}" match="__ACTIVITY__" replace="${activity}" />
|
||||
<replaceregexp file="${activity.path}" match="__ID__" replace="${package}" />
|
||||
|
||||
<replaceregexp file="${manifest.path}" match="__ACTIVITY__" replace="${activity}" />
|
||||
<replaceregexp file="${manifest.path}" match="__PACKAGE__" replace="${package}" />
|
||||
</target>
|
||||
</project>
|
||||
65
bin/lib/android_sdk_version.js
Executable file
65
bin/lib/android_sdk_version.js
Executable file
@@ -0,0 +1,65 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
|
||||
var shell = require('shelljs'),
|
||||
child_process = require('child_process'),
|
||||
Q = require('q');
|
||||
|
||||
get_highest_sdk = function(results){
|
||||
var reg = /\d+/;
|
||||
var apiLevels = [];
|
||||
for(var i=0;i<results.length;i++){
|
||||
apiLevels[i] = parseInt(results[i].match(reg)[0]);
|
||||
}
|
||||
apiLevels.sort(function(a,b){return b-a});
|
||||
console.log(apiLevels[0]);
|
||||
}
|
||||
|
||||
get_sdks = function() {
|
||||
var d = Q.defer();
|
||||
child_process.exec('android list targets', function(err, stdout, stderr) {
|
||||
if (err) d.reject(stderr);
|
||||
else d.resolve(stdout);
|
||||
});
|
||||
|
||||
return d.promise.then(function(output) {
|
||||
var reg = /android-\d+/gi;
|
||||
var results = output.match(reg);
|
||||
if(results.length===0){
|
||||
return Q.reject(new Error('No android sdks installed.'));
|
||||
}else{
|
||||
get_highest_sdk(results);
|
||||
}
|
||||
|
||||
return Q();
|
||||
}, function(stderr) {
|
||||
if (stderr.match(/command\snot\sfound/) || stderr.match(/'android' is not recognized/)) {
|
||||
return Q.reject(new Error('The command \"android\" failed. Make sure you have the latest Android SDK installed, and the \"android\" command (inside the tools/ folder) is added to your path.'));
|
||||
} else {
|
||||
return Q.reject(new Error('An error occurred while listing Android targets'));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
module.exports.run = function() {
|
||||
return Q.all([get_sdks()]);
|
||||
}
|
||||
|
||||
242
bin/lib/check_reqs.js
Normal file
242
bin/lib/check_reqs.js
Normal file
@@ -0,0 +1,242 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
|
||||
var shelljs = require('shelljs'),
|
||||
child_process = require('child_process'),
|
||||
Q = require('q'),
|
||||
path = require('path'),
|
||||
fs = require('fs'),
|
||||
which = require('which'),
|
||||
ROOT = path.join(__dirname, '..', '..');
|
||||
|
||||
var isWindows = process.platform == 'win32';
|
||||
|
||||
function forgivingWhichSync(cmd) {
|
||||
try {
|
||||
return fs.realpathSync(which.sync(cmd));
|
||||
} catch (e) {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
function tryCommand(cmd, errMsg) {
|
||||
var d = Q.defer();
|
||||
child_process.exec(cmd, function(err, stdout, stderr) {
|
||||
if (err) d.reject(new Error(errMsg));
|
||||
else d.resolve(stdout);
|
||||
});
|
||||
return d.promise;
|
||||
}
|
||||
|
||||
// Get valid target from framework/project.properties
|
||||
module.exports.get_target = function() {
|
||||
function extractFromFile(filePath) {
|
||||
var target = shelljs.grep(/\btarget=/, filePath);
|
||||
if (!target) {
|
||||
throw new Error('Could not find android target within: ' + filePath);
|
||||
}
|
||||
return target.split('=')[1].trim();
|
||||
}
|
||||
if (fs.existsSync(path.join(ROOT, 'framework', 'project.properties'))) {
|
||||
return extractFromFile(path.join(ROOT, 'framework', 'project.properties'));
|
||||
}
|
||||
if (fs.existsSync(path.join(ROOT, 'project.properties'))) {
|
||||
// if no target found, we're probably in a project and project.properties is in ROOT.
|
||||
return extractFromFile(path.join(ROOT, 'project.properties'));
|
||||
}
|
||||
throw new Error('Could not find android target. File missing: ' + path.join(ROOT, 'project.properties'));
|
||||
}
|
||||
|
||||
// Returns a promise. Called only by build and clean commands.
|
||||
module.exports.check_ant = function() {
|
||||
return tryCommand('ant -version', 'Failed to run "ant -version", make sure you have ant installed and added to your PATH.');
|
||||
};
|
||||
|
||||
// Returns a promise. Called only by build and clean commands.
|
||||
module.exports.check_gradle = function() {
|
||||
var sdkDir = process.env['ANDROID_HOME'];
|
||||
var wrapperDir = path.join(sdkDir, 'tools', 'templates', 'gradle', 'wrapper');
|
||||
if (!fs.existsSync(wrapperDir)) {
|
||||
return Q.reject(new Error('Could not find gradle wrapper within android sdk. Might need to update your Android SDK.\n' +
|
||||
'Looked here: ' + wrapperDir));
|
||||
}
|
||||
return Q.when();
|
||||
};
|
||||
|
||||
// Returns a promise.
|
||||
module.exports.check_java = function() {
|
||||
var javacPath = forgivingWhichSync('javac');
|
||||
var hasJavaHome = !!process.env['JAVA_HOME'];
|
||||
return Q().then(function() {
|
||||
if (hasJavaHome) {
|
||||
// Windows java installer doesn't add javac to PATH, nor set JAVA_HOME (ugh).
|
||||
if (!javacPath) {
|
||||
process.env['PATH'] += path.delimiter + path.join(process.env['JAVA_HOME'], 'bin');
|
||||
}
|
||||
} else {
|
||||
if (javacPath) {
|
||||
// OS X has a command for finding JAVA_HOME.
|
||||
if (fs.existsSync('/usr/libexec/java_home')) {
|
||||
return tryCommand('/usr/libexec/java_home', 'Failed to run: /usr/libexec/java_home')
|
||||
.then(function(stdout) {
|
||||
process.env['JAVA_HOME'] = stdout.trim();
|
||||
});
|
||||
} else {
|
||||
// See if we can derive it from javac's location.
|
||||
// fs.realpathSync is require on Ubuntu, which symplinks from /usr/bin -> JDK
|
||||
var maybeJavaHome = path.dirname(path.dirname(javacPath));
|
||||
if (fs.existsSync(path.join(maybeJavaHome, 'lib', 'tools.jar'))) {
|
||||
process.env['JAVA_HOME'] = maybeJavaHome;
|
||||
} else {
|
||||
throw new Error('Could not find JAVA_HOME. Try setting the environment variable manually');
|
||||
}
|
||||
}
|
||||
} else if (isWindows) {
|
||||
// Try to auto-detect java in the default install paths.
|
||||
var oldSilent = shelljs.config.silent;
|
||||
shelljs.config.silent = true;
|
||||
var firstJdkDir =
|
||||
shelljs.ls(process.env['ProgramFiles'] + '\\java\\jdk*')[0] ||
|
||||
shelljs.ls('C:\\Program Files\\java\\jdk*')[0] ||
|
||||
shelljs.ls('C:\\Program Files (x86)\\java\\jdk*')[0];
|
||||
shelljs.config.silent = oldSilent;
|
||||
if (firstJdkDir) {
|
||||
// shelljs always uses / in paths.
|
||||
firstJdkDir = firstJdkDir.replace(/\//g, path.sep);
|
||||
if (!javacPath) {
|
||||
process.env['PATH'] += path.delimiter + path.join(firstJdkDir, 'bin');
|
||||
}
|
||||
process.env['JAVA_HOME'] = firstJdkDir;
|
||||
}
|
||||
}
|
||||
}
|
||||
}).then(function() {
|
||||
var msg =
|
||||
'Failed to run "java -version", make sure that you have a JDK installed.\n' +
|
||||
'You can get it from: http://www.oracle.com/technetwork/java/javase/downloads.\n';
|
||||
if (process.env['JAVA_HOME']) {
|
||||
msg += 'Your JAVA_HOME is invalid: ' + process.env['JAVA_HOME'] + '\n';
|
||||
}
|
||||
return tryCommand('java -version', msg)
|
||||
.then(function() {
|
||||
return tryCommand('javac -version', msg);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Returns a promise.
|
||||
module.exports.check_android = function() {
|
||||
return Q().then(function() {
|
||||
var androidCmdPath = forgivingWhichSync('android');
|
||||
var adbInPath = !!forgivingWhichSync('adb');
|
||||
var hasAndroidHome = !!process.env['ANDROID_HOME'] && fs.existsSync(process.env['ANDROID_HOME']);
|
||||
function maybeSetAndroidHome(value) {
|
||||
if (!hasAndroidHome && fs.existsSync(value)) {
|
||||
hasAndroidHome = true;
|
||||
process.env['ANDROID_HOME'] = value;
|
||||
}
|
||||
}
|
||||
if (!hasAndroidHome && !androidCmdPath) {
|
||||
if (isWindows) {
|
||||
// Android Studio 1.0 installer
|
||||
maybeSetAndroidHome(path.join(process.env['LOCALAPPDATA'], 'Android', 'sdk'));
|
||||
maybeSetAndroidHome(path.join(process.env['ProgramFiles'], 'Android', 'sdk'));
|
||||
// Android Studio pre-1.0 installer
|
||||
maybeSetAndroidHome(path.join(process.env['LOCALAPPDATA'], 'Android', 'android-studio', 'sdk'));
|
||||
maybeSetAndroidHome(path.join(process.env['ProgramFiles'], 'Android', 'android-studio', 'sdk'));
|
||||
// Stand-alone installer
|
||||
maybeSetAndroidHome(path.join(process.env['LOCALAPPDATA'], 'Android', 'android-sdk'));
|
||||
maybeSetAndroidHome(path.join(process.env['ProgramFiles'], 'Android', 'android-sdk'));
|
||||
} else if (process.platform == 'darwin') {
|
||||
// Android Studio 1.0 installer
|
||||
maybeSetAndroidHome(path.join(process.env['HOME'], 'Library', 'Android', 'sdk'));
|
||||
// Android Studio pre-1.0 installer
|
||||
maybeSetAndroidHome('/Applications/Android Studio.app/sdk');
|
||||
// Stand-alone zip file that user might think to put under /Applications
|
||||
maybeSetAndroidHome('/Applications/android-sdk-macosx');
|
||||
maybeSetAndroidHome('/Applications/android-sdk');
|
||||
}
|
||||
if (process.env['HOME']) {
|
||||
// Stand-alone zip file that user might think to put under their home directory
|
||||
maybeSetAndroidHome(path.join(process.env['HOME'], 'android-sdk-macosx'));
|
||||
maybeSetAndroidHome(path.join(process.env['HOME'], 'android-sdk'));
|
||||
}
|
||||
}
|
||||
if (hasAndroidHome && !androidCmdPath) {
|
||||
process.env['PATH'] += path.delimiter + path.join(process.env['ANDROID_HOME'], 'tools');
|
||||
}
|
||||
if (androidCmdPath && !hasAndroidHome) {
|
||||
var parentDir = path.dirname(androidCmdPath);
|
||||
var grandParentDir = path.dirname(parentDir);
|
||||
if (path.basename(parentDir) == 'tools') {
|
||||
process.env['ANDROID_HOME'] = path.dirname(parentDir);
|
||||
hasAndroidHome = true;
|
||||
} else if (fs.existsSync(path.join(grandParentDir, 'tools', 'android'))) {
|
||||
process.env['ANDROID_HOME'] = grandParentDir;
|
||||
hasAndroidHome = true;
|
||||
} else {
|
||||
throw new Error('ANDROID_HOME is not set and no "tools" directory found at ' + parentDir);
|
||||
}
|
||||
}
|
||||
if (hasAndroidHome && !adbInPath) {
|
||||
process.env['PATH'] += path.delimiter + path.join(process.env['ANDROID_HOME'], 'platform-tools');
|
||||
}
|
||||
if (!process.env['ANDROID_HOME']) {
|
||||
throw new Error('ANDROID_HOME is not set and "android" command not in your PATH. You must fulfill at least one of these conditions.');
|
||||
}
|
||||
if (!fs.existsSync(process.env['ANDROID_HOME'])) {
|
||||
throw new Error('ANDROID_HOME is set to a non-existant path: ' + process.env['ANDROID_HOME']);
|
||||
}
|
||||
// Check that the target sdk level is installed.
|
||||
return module.exports.check_android_target(module.exports.get_target());
|
||||
});
|
||||
};
|
||||
|
||||
module.exports.getAbsoluteAndroidCmd = function() {
|
||||
return forgivingWhichSync('android').replace(/(\s)/g, '\\$1');
|
||||
};
|
||||
|
||||
module.exports.check_android_target = function(valid_target) {
|
||||
// valid_target can look like:
|
||||
// android-19
|
||||
// android-L
|
||||
// Google Inc.:Google APIs:20
|
||||
// Google Inc.:Glass Development Kit Preview:20
|
||||
var msg = 'Android SDK not found. Make sure that it is installed. If it is not at the default location, set the ANDROID_HOME environment variable.';
|
||||
return tryCommand('android list targets --compact', msg)
|
||||
.then(function(output) {
|
||||
if (output.split('\n').indexOf(valid_target) == -1) {
|
||||
var androidCmd = module.exports.getAbsoluteAndroidCmd();
|
||||
throw new Error('Please install Android target: "' + valid_target + '".\n\n' +
|
||||
'Hint: Open the SDK manager by running: ' + androidCmd + '\n' +
|
||||
'You will require:\n' +
|
||||
'1. "SDK Platform" for ' + valid_target + '\n' +
|
||||
'2. "Android SDK Platform-tools (latest)\n' +
|
||||
'3. "Android SDK Build-tools" (latest)');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// Returns a promise.
|
||||
module.exports.run = function() {
|
||||
return Q.all([this.check_java(), this.check_android()]);
|
||||
}
|
||||
|
||||
323
bin/lib/create.js
Executable file
323
bin/lib/create.js
Executable file
@@ -0,0 +1,323 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
var shell = require('shelljs'),
|
||||
child_process = require('child_process'),
|
||||
Q = require('q'),
|
||||
path = require('path'),
|
||||
fs = require('fs'),
|
||||
check_reqs = require('./check_reqs'),
|
||||
ROOT = path.join(__dirname, '..', '..');
|
||||
|
||||
// Returns a promise.
|
||||
function exec(command, opt_cwd) {
|
||||
var d = Q.defer();
|
||||
console.log('Running: ' + command);
|
||||
child_process.exec(command, { cwd: opt_cwd }, function(err, stdout, stderr) {
|
||||
stdout && console.log(stdout);
|
||||
stderr && console.error(stderr);
|
||||
if (err) d.reject(err);
|
||||
else d.resolve(stdout);
|
||||
});
|
||||
return d.promise;
|
||||
}
|
||||
|
||||
function setShellFatal(value, func) {
|
||||
var oldVal = shell.config.fatal;
|
||||
shell.config.fatal = value;
|
||||
func();
|
||||
shell.config.fatal = oldVal;
|
||||
}
|
||||
|
||||
function getFrameworkDir(projectPath, shared) {
|
||||
return shared ? path.join(ROOT, 'framework') : path.join(projectPath, 'CordovaLib');
|
||||
}
|
||||
|
||||
function copyJsAndLibrary(projectPath, shared, projectName) {
|
||||
var nestedCordovaLibPath = getFrameworkDir(projectPath, false);
|
||||
shell.cp('-f', path.join(ROOT, 'framework', 'assets', 'www', 'cordova.js'), path.join(projectPath, 'assets', 'www', 'cordova.js'));
|
||||
// Don't fail if there are no old jars.
|
||||
setShellFatal(false, function() {
|
||||
shell.ls(path.join(projectPath, 'libs', 'cordova-*.jar')).forEach(function(oldJar) {
|
||||
console.log("Deleting " + oldJar);
|
||||
shell.rm('-f', oldJar);
|
||||
});
|
||||
// Delete old library project if it existed.
|
||||
if (shared) {
|
||||
shell.rm('-rf', nestedCordovaLibPath);
|
||||
} else {
|
||||
// Delete only the src, since eclipse can't handle its .project file being deleted.
|
||||
shell.rm('-rf', path.join(nestedCordovaLibPath, 'src'));
|
||||
}
|
||||
});
|
||||
if (!shared) {
|
||||
shell.mkdir('-p', nestedCordovaLibPath);
|
||||
shell.cp('-f', path.join(ROOT, 'framework', 'AndroidManifest.xml'), nestedCordovaLibPath);
|
||||
shell.cp('-f', path.join(ROOT, 'framework', 'project.properties'), nestedCordovaLibPath);
|
||||
shell.cp('-f', path.join(ROOT, 'framework', 'build.gradle'), nestedCordovaLibPath);
|
||||
shell.cp('-f', path.join(ROOT, 'framework', 'cordova.gradle'), nestedCordovaLibPath);
|
||||
shell.cp('-r', path.join(ROOT, 'framework', 'src'), nestedCordovaLibPath);
|
||||
// Create an eclipse project file and set the name of it to something unique.
|
||||
// Without this, you can't import multiple CordovaLib projects into the same workspace.
|
||||
var eclipseProjectFilePath = path.join(nestedCordovaLibPath, '.project');
|
||||
if (!fs.existsSync(eclipseProjectFilePath)) {
|
||||
var data = '<?xml version="1.0" encoding="UTF-8"?><projectDescription><name>' + projectName + '-' + 'CordovaLib</name></projectDescription>';
|
||||
fs.writeFileSync(eclipseProjectFilePath, data, 'utf8');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function extractSubProjectPaths(data) {
|
||||
var ret = {};
|
||||
var r = /^\s*android\.library\.reference\.\d+=(.*)(?:\s|$)/mg
|
||||
var m;
|
||||
while (m = r.exec(data)) {
|
||||
ret[m[1]] = 1;
|
||||
}
|
||||
return Object.keys(ret);
|
||||
}
|
||||
|
||||
function writeProjectProperties(projectPath, target_api, shared) {
|
||||
var dstPath = path.join(projectPath, 'project.properties');
|
||||
var templatePath = path.join(ROOT, 'bin', 'templates', 'project', 'project.properties');
|
||||
var srcPath = fs.existsSync(dstPath) ? dstPath : templatePath;
|
||||
var data = fs.readFileSync(srcPath, 'utf8');
|
||||
data = data.replace(/^target=.*/m, 'target=' + target_api);
|
||||
var subProjects = extractSubProjectPaths(data);
|
||||
subProjects = subProjects.filter(function(p) {
|
||||
return !(/^CordovaLib$/m.exec(p) ||
|
||||
/[\\\/]cordova-android[\\\/]framework$/m.exec(p) ||
|
||||
/^(\.\.[\\\/])+framework$/m.exec(p)
|
||||
);
|
||||
});
|
||||
subProjects.unshift(shared ? path.relative(projectPath, path.join(ROOT, 'framework')) : 'CordovaLib');
|
||||
data = data.replace(/^\s*android\.library\.reference\.\d+=.*\n/mg, '');
|
||||
if (!/\n$/.exec(data)) {
|
||||
data += '\n';
|
||||
}
|
||||
for (var i = 0; i < subProjects.length; ++i) {
|
||||
data += 'android.library.reference.' + (i+1) + '=' + subProjects[i] + '\n';
|
||||
}
|
||||
fs.writeFileSync(dstPath, data);
|
||||
}
|
||||
|
||||
function copyBuildRules(projectPath) {
|
||||
var srcDir = path.join(ROOT, 'bin', 'templates', 'project');
|
||||
shell.cp('-f', path.join(srcDir, 'custom_rules.xml'), projectPath);
|
||||
|
||||
shell.cp('-f', path.join(srcDir, 'build.gradle'), projectPath);
|
||||
}
|
||||
|
||||
function copyScripts(projectPath) {
|
||||
var srcScriptsDir = path.join(ROOT, 'bin', 'templates', 'cordova');
|
||||
var destScriptsDir = path.join(projectPath, 'cordova');
|
||||
// Delete old scripts directory if this is an update.
|
||||
shell.rm('-rf', destScriptsDir);
|
||||
// Copy in the new ones.
|
||||
shell.cp('-r', srcScriptsDir, projectPath);
|
||||
shell.cp('-r', path.join(ROOT, 'bin', 'node_modules'), destScriptsDir);
|
||||
shell.cp(path.join(ROOT, 'bin', 'check_reqs'), path.join(destScriptsDir, 'check_reqs'));
|
||||
shell.cp(path.join(ROOT, 'bin', 'lib', 'check_reqs.js'), path.join(projectPath, 'cordova', 'lib', 'check_reqs.js'));
|
||||
shell.cp(path.join(ROOT, 'bin', 'android_sdk_version'), path.join(destScriptsDir, 'android_sdk_version'));
|
||||
shell.cp(path.join(ROOT, 'bin', 'lib', 'android_sdk_version.js'), path.join(projectPath, 'cordova', 'lib', 'android_sdk_version.js'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test whether a package name is acceptable for use as an android project.
|
||||
* Returns a promise, fulfilled if the package name is acceptable; rejected
|
||||
* otherwise.
|
||||
*/
|
||||
function validatePackageName(package_name) {
|
||||
//Make the package conform to Java package types
|
||||
//Enforce underscore limitation
|
||||
if (!/^[a-zA-Z]+(\.[a-zA-Z0-9][a-zA-Z0-9_]*)+$/.test(package_name)) {
|
||||
return Q.reject('Package name must look like: com.company.Name');
|
||||
}
|
||||
|
||||
//Class is a reserved word
|
||||
if(/\b[Cc]lass\b/.test(package_name)) {
|
||||
return Q.reject('class is a reserved word');
|
||||
}
|
||||
|
||||
return Q.resolve();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test whether a project name is acceptable for use as an android class.
|
||||
* Returns a promise, fulfilled if the project name is acceptable; rejected
|
||||
* otherwise.
|
||||
*/
|
||||
function validateProjectName(project_name) {
|
||||
//Make sure there's something there
|
||||
if (project_name === '') {
|
||||
return Q.reject('Project name cannot be empty');
|
||||
}
|
||||
|
||||
//Enforce stupid name error
|
||||
if (project_name === 'CordovaActivity') {
|
||||
return Q.reject('Project name cannot be CordovaActivity');
|
||||
}
|
||||
|
||||
//Classes in Java don't begin with numbers
|
||||
if (/^[0-9]/.test(project_name)) {
|
||||
return Q.reject('Project name must not begin with a number');
|
||||
}
|
||||
|
||||
return Q.resolve();
|
||||
}
|
||||
|
||||
/**
|
||||
* $ create [options]
|
||||
*
|
||||
* Creates an android application with the given options.
|
||||
*
|
||||
* Options:
|
||||
*
|
||||
* - `project_path` {String} Path to the new Cordova android project.
|
||||
* - `package_name`{String} Package name, following reverse-domain style convention.
|
||||
* - `project_name` {String} Project name.
|
||||
* - 'project_template_dir' {String} Path to project template (override).
|
||||
*
|
||||
* Returns a promise.
|
||||
*/
|
||||
|
||||
exports.createProject = function(project_path, package_name, project_name, project_template_dir, use_shared_project, use_cli_template) {
|
||||
var VERSION = fs.readFileSync(path.join(ROOT, 'VERSION'), 'utf-8').trim();
|
||||
|
||||
// Set default values for path, package and name
|
||||
project_path = typeof project_path !== 'undefined' ? project_path : "CordovaExample";
|
||||
project_path = path.relative(process.cwd(), project_path);
|
||||
package_name = typeof package_name !== 'undefined' ? package_name : 'my.cordova.project';
|
||||
project_name = typeof project_name !== 'undefined' ? project_name : 'CordovaExample';
|
||||
project_template_dir = typeof project_template_dir !== 'undefined' ?
|
||||
project_template_dir :
|
||||
path.join(ROOT, 'bin', 'templates', 'project');
|
||||
|
||||
var package_as_path = package_name.replace(/\./g, path.sep);
|
||||
var activity_dir = path.join(project_path, 'src', package_as_path);
|
||||
// safe_activity_name is being hardcoded to avoid issues with unicode app name (https://issues.apache.org/jira/browse/CB-6511)
|
||||
// TODO: provide option to specify activity name via CLI (proposal: https://issues.apache.org/jira/browse/CB-7231)
|
||||
var safe_activity_name = 'MainActivity';
|
||||
var activity_path = path.join(activity_dir, safe_activity_name + '.java');
|
||||
var target_api = check_reqs.get_target();
|
||||
var manifest_path = path.join(project_path, 'AndroidManifest.xml');
|
||||
|
||||
// Check if project already exists
|
||||
if(fs.existsSync(project_path)) {
|
||||
return Q.reject('Project already exists! Delete and recreate');
|
||||
}
|
||||
|
||||
//Make the package conform to Java package types
|
||||
return validatePackageName(package_name)
|
||||
.then(function() {
|
||||
validateProjectName(project_name);
|
||||
}).then(function() {
|
||||
// Log the given values for the project
|
||||
console.log('Creating Cordova project for the Android platform:');
|
||||
console.log('\tPath: ' + project_path);
|
||||
console.log('\tPackage: ' + package_name);
|
||||
console.log('\tName: ' + project_name);
|
||||
console.log('\tAndroid target: ' + target_api);
|
||||
|
||||
console.log('Copying template files...');
|
||||
|
||||
setShellFatal(true, function() {
|
||||
// copy project template
|
||||
shell.cp('-r', path.join(project_template_dir, 'assets'), project_path);
|
||||
shell.cp('-r', path.join(project_template_dir, 'res'), project_path);
|
||||
shell.cp('-r', path.join(ROOT, 'framework', 'res', 'xml'), path.join(project_path, 'res'));
|
||||
shell.cp(path.join(project_template_dir, 'gitignore'), path.join(project_path, '.gitignore'));
|
||||
|
||||
// Manually create directories that would be empty within the template (since git doesn't track directories).
|
||||
shell.mkdir(path.join(project_path, 'libs'));
|
||||
|
||||
// Add in the proper eclipse project file.
|
||||
if (use_cli_template) {
|
||||
var note = 'To show `assets/www` or `res/xml/config.xml`, go to:\n' +
|
||||
' Project -> Properties -> Resource -> Resource Filters\n' +
|
||||
'And delete the exclusion filter.\n';
|
||||
shell.cp(path.join(project_template_dir, 'eclipse-project-CLI'), path.join(project_path, '.project'));
|
||||
fs.writeFileSync(path.join(project_path, 'assets', '_where-is-www.txt'), note);
|
||||
} else {
|
||||
shell.cp(path.join(project_template_dir, 'eclipse-project'), path.join(project_path, '.project'));
|
||||
}
|
||||
|
||||
// copy cordova.js, cordova.jar
|
||||
copyJsAndLibrary(project_path, use_shared_project, safe_activity_name);
|
||||
|
||||
// interpolate the activity name and package
|
||||
shell.mkdir('-p', activity_dir);
|
||||
shell.cp('-f', path.join(project_template_dir, 'Activity.java'), activity_path);
|
||||
shell.sed('-i', /__ACTIVITY__/, safe_activity_name, activity_path);
|
||||
shell.sed('-i', /__NAME__/, project_name, path.join(project_path, 'res', 'values', 'strings.xml'));
|
||||
shell.sed('-i', /__NAME__/, project_name, path.join(project_path, '.project'));
|
||||
shell.sed('-i', /__ID__/, package_name, activity_path);
|
||||
|
||||
shell.cp('-f', path.join(project_template_dir, 'AndroidManifest.xml'), manifest_path);
|
||||
shell.sed('-i', /__ACTIVITY__/, safe_activity_name, manifest_path);
|
||||
shell.sed('-i', /__PACKAGE__/, package_name, manifest_path);
|
||||
shell.sed('-i', /__APILEVEL__/, target_api.split('-')[1], manifest_path);
|
||||
copyScripts(project_path);
|
||||
copyBuildRules(project_path);
|
||||
});
|
||||
// Link it to local android install.
|
||||
writeProjectProperties(project_path, target_api, use_shared_project);
|
||||
}).then(function() {
|
||||
console.log('Project successfully created.');
|
||||
});
|
||||
}
|
||||
|
||||
// Attribute removed in Cordova 4.4 (CB-5447).
|
||||
function removeDebuggableFromManifest(projectPath) {
|
||||
var manifestPath = path.join(projectPath, 'AndroidManifest.xml');
|
||||
shell.sed('-i', /\s*android:debuggable="true"/, '', manifestPath);
|
||||
}
|
||||
|
||||
function extractProjectNameFromManifest(projectPath) {
|
||||
var manifestPath = path.join(projectPath, 'AndroidManifest.xml');
|
||||
var manifestData = fs.readFileSync(manifestPath, 'utf8');
|
||||
var m = /<activity[\s\S]*?android:name\s*=\s*"(.*?)"/i.exec(manifestData);
|
||||
if (!m) {
|
||||
throw new Error('Could not find activity name in ' + manifestPath);
|
||||
}
|
||||
return m[1];
|
||||
}
|
||||
|
||||
// Returns a promise.
|
||||
exports.updateProject = function(projectPath, shared) {
|
||||
var newVersion = fs.readFileSync(path.join(ROOT, 'VERSION'), 'utf-8').trim();
|
||||
return Q()
|
||||
.then(function() {
|
||||
var projectName = extractProjectNameFromManifest(projectPath);
|
||||
var target_api = check_reqs.get_target();
|
||||
copyJsAndLibrary(projectPath, shared, projectName);
|
||||
copyScripts(projectPath);
|
||||
copyBuildRules(projectPath);
|
||||
removeDebuggableFromManifest(projectPath);
|
||||
writeProjectProperties(projectPath, target_api, shared);
|
||||
console.log('Android project is now at version ' + newVersion);
|
||||
console.log('If you updated from a pre-3.2.0 version and use an IDE, we now require that you import the "CordovaLib" library project.');
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
// For testing
|
||||
exports.validatePackageName = validatePackageName;
|
||||
exports.validateProjectName = validateProjectName;
|
||||
32
bin/lib/simpleargs.js
Normal file
32
bin/lib/simpleargs.js
Normal file
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
|
||||
exports.getArgs = function(argv) {
|
||||
var ret = {};
|
||||
var posArgs = [];
|
||||
for (var i = 2, arg; arg = argv[i] || i < argv.length; ++i) {
|
||||
if (/^--/.exec(arg)) {
|
||||
ret[arg] = true;
|
||||
} else {
|
||||
posArgs.push(arg);
|
||||
}
|
||||
}
|
||||
ret._ = posArgs;
|
||||
return ret;
|
||||
};
|
||||
1
bin/node_modules/.bin/shjs
generated
vendored
Symbolic link
1
bin/node_modules/.bin/shjs
generated
vendored
Symbolic link
@@ -0,0 +1 @@
|
||||
../shelljs/bin/shjs
|
||||
40
bin/node_modules/q/CONTRIBUTING.md
generated
vendored
Normal file
40
bin/node_modules/q/CONTRIBUTING.md
generated
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
|
||||
For pull requests:
|
||||
|
||||
- Be consistent with prevalent style and design decisions.
|
||||
- Add a Jasmine spec to `specs/q-spec.js`.
|
||||
- Use `npm test` to avoid regressions.
|
||||
- Run tests in `q-spec/run.html` in as many supported browsers as you
|
||||
can find the will to deal with.
|
||||
- Do not build minified versions; we do this each release.
|
||||
- If you would be so kind, add a note to `CHANGES.md` in an
|
||||
appropriate section:
|
||||
|
||||
- `Next Major Version` if it introduces backward incompatibilities
|
||||
to code in the wild using documented features.
|
||||
- `Next Minor Version` if it adds a new feature.
|
||||
- `Next Patch Version` if it fixes a bug.
|
||||
|
||||
For releases:
|
||||
|
||||
- Run `npm test`.
|
||||
- Run tests in `q-spec/run.html` in a representative sample of every
|
||||
browser under the sun.
|
||||
- Run `npm run cover` and make sure you're happy with the results.
|
||||
- Run `npm run minify` and be sure to commit the resulting `q.min.js`.
|
||||
- Note the Gzipped size output by the previous command, and update
|
||||
`README.md` if it has changed to 1 significant digit.
|
||||
- Stash any local changes.
|
||||
- Update `CHANGES.md` to reflect all changes in the differences
|
||||
between `HEAD` and the previous tagged version. Give credit where
|
||||
credit is due.
|
||||
- Update `README.md` to address all new, non-experimental features.
|
||||
- Update the API reference on the Wiki to reflect all non-experimental
|
||||
features.
|
||||
- Use `npm version major|minor|patch` to update `package.json`,
|
||||
commit, and tag the new version.
|
||||
- Use `npm publish` to send up a new release.
|
||||
- Send an email to the q-continuum mailing list announcing the new
|
||||
release and the notes from the change log. This helps folks
|
||||
maintaining other package ecosystems.
|
||||
|
||||
19
bin/node_modules/q/LICENSE
generated
vendored
Normal file
19
bin/node_modules/q/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
|
||||
Copyright 2009–2012 Kristopher Michael Kowal. All rights reserved.
|
||||
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.
|
||||
813
bin/node_modules/q/README.md
generated
vendored
Normal file
813
bin/node_modules/q/README.md
generated
vendored
Normal file
@@ -0,0 +1,813 @@
|
||||
[](http://travis-ci.org/kriskowal/q)
|
||||
|
||||
<a href="http://promises-aplus.github.com/promises-spec">
|
||||
<img src="http://promises-aplus.github.com/promises-spec/assets/logo-small.png"
|
||||
align="right" alt="Promises/A+ logo" />
|
||||
</a>
|
||||
|
||||
If a function cannot return a value or throw an exception without
|
||||
blocking, it can return a promise instead. A promise is an object
|
||||
that represents the return value or the thrown exception that the
|
||||
function may eventually provide. A promise can also be used as a
|
||||
proxy for a [remote object][Q-Connection] to overcome latency.
|
||||
|
||||
[Q-Connection]: https://github.com/kriskowal/q-connection
|
||||
|
||||
On the first pass, promises can mitigate the “[Pyramid of
|
||||
Doom][POD]”: the situation where code marches to the right faster
|
||||
than it marches forward.
|
||||
|
||||
[POD]: http://calculist.org/blog/2011/12/14/why-coroutines-wont-work-on-the-web/
|
||||
|
||||
```javascript
|
||||
step1(function (value1) {
|
||||
step2(value1, function(value2) {
|
||||
step3(value2, function(value3) {
|
||||
step4(value3, function(value4) {
|
||||
// Do something with value4
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
With a promise library, you can flatten the pyramid.
|
||||
|
||||
```javascript
|
||||
Q.fcall(promisedStep1)
|
||||
.then(promisedStep2)
|
||||
.then(promisedStep3)
|
||||
.then(promisedStep4)
|
||||
.then(function (value4) {
|
||||
// Do something with value4
|
||||
})
|
||||
.catch(function (error) {
|
||||
// Handle any error from all above steps
|
||||
})
|
||||
.done();
|
||||
```
|
||||
|
||||
With this approach, you also get implicit error propagation, just like `try`,
|
||||
`catch`, and `finally`. An error in `promisedStep1` will flow all the way to
|
||||
the `catch` function, where it’s caught and handled. (Here `promisedStepN` is
|
||||
a version of `stepN` that returns a promise.)
|
||||
|
||||
The callback approach is called an “inversion of control”.
|
||||
A function that accepts a callback instead of a return value
|
||||
is saying, “Don’t call me, I’ll call you.”. Promises
|
||||
[un-invert][IOC] the inversion, cleanly separating the input
|
||||
arguments from control flow arguments. This simplifies the
|
||||
use and creation of API’s, particularly variadic,
|
||||
rest and spread arguments.
|
||||
|
||||
[IOC]: http://www.slideshare.net/domenicdenicola/callbacks-promises-and-coroutines-oh-my-the-evolution-of-asynchronicity-in-javascript
|
||||
|
||||
|
||||
## Getting Started
|
||||
|
||||
The Q module can be loaded as:
|
||||
|
||||
- A ``<script>`` tag (creating a ``Q`` global variable): ~2.5 KB minified and
|
||||
gzipped.
|
||||
- A Node.js and CommonJS module, available in [npm](https://npmjs.org/) as
|
||||
the [q](https://npmjs.org/package/q) package
|
||||
- An AMD module
|
||||
- A [component](https://github.com/component/component) as ``microjs/q``
|
||||
- Using [bower](http://bower.io/) as ``q``
|
||||
- Using [NuGet](http://nuget.org/) as [Q](https://nuget.org/packages/q)
|
||||
|
||||
Q can exchange promises with jQuery, Dojo, When.js, WinJS, and more.
|
||||
|
||||
## Resources
|
||||
|
||||
Our [wiki][] contains a number of useful resources, including:
|
||||
|
||||
- A method-by-method [Q API reference][reference].
|
||||
- A growing [examples gallery][examples], showing how Q can be used to make
|
||||
everything better. From XHR to database access to accessing the Flickr API,
|
||||
Q is there for you.
|
||||
- There are many libraries that produce and consume Q promises for everything
|
||||
from file system/database access or RPC to templating. For a list of some of
|
||||
the more popular ones, see [Libraries][].
|
||||
- If you want materials that introduce the promise concept generally, and the
|
||||
below tutorial isn't doing it for you, check out our collection of
|
||||
[presentations, blog posts, and podcasts][resources].
|
||||
- A guide for those [coming from jQuery's `$.Deferred`][jquery].
|
||||
|
||||
We'd also love to have you join the Q-Continuum [mailing list][].
|
||||
|
||||
[wiki]: https://github.com/kriskowal/q/wiki
|
||||
[reference]: https://github.com/kriskowal/q/wiki/API-Reference
|
||||
[examples]: https://github.com/kriskowal/q/wiki/Examples-Gallery
|
||||
[Libraries]: https://github.com/kriskowal/q/wiki/Libraries
|
||||
[resources]: https://github.com/kriskowal/q/wiki/General-Promise-Resources
|
||||
[jquery]: https://github.com/kriskowal/q/wiki/Coming-from-jQuery
|
||||
[mailing list]: https://groups.google.com/forum/#!forum/q-continuum
|
||||
|
||||
|
||||
## Tutorial
|
||||
|
||||
Promises have a ``then`` method, which you can use to get the eventual
|
||||
return value (fulfillment) or thrown exception (rejection).
|
||||
|
||||
```javascript
|
||||
promiseMeSomething()
|
||||
.then(function (value) {
|
||||
}, function (reason) {
|
||||
});
|
||||
```
|
||||
|
||||
If ``promiseMeSomething`` returns a promise that gets fulfilled later
|
||||
with a return value, the first function (the fulfillment handler) will be
|
||||
called with the value. However, if the ``promiseMeSomething`` function
|
||||
gets rejected later by a thrown exception, the second function (the
|
||||
rejection handler) will be called with the exception.
|
||||
|
||||
Note that resolution of a promise is always asynchronous: that is, the
|
||||
fulfillment or rejection handler will always be called in the next turn of the
|
||||
event loop (i.e. `process.nextTick` in Node). This gives you a nice
|
||||
guarantee when mentally tracing the flow of your code, namely that
|
||||
``then`` will always return before either handler is executed.
|
||||
|
||||
In this tutorial, we begin with how to consume and work with promises. We'll
|
||||
talk about how to create them, and thus create functions like
|
||||
`promiseMeSomething` that return promises, [below](#the-beginning).
|
||||
|
||||
|
||||
### Propagation
|
||||
|
||||
The ``then`` method returns a promise, which in this example, I’m
|
||||
assigning to ``outputPromise``.
|
||||
|
||||
```javascript
|
||||
var outputPromise = getInputPromise()
|
||||
.then(function (input) {
|
||||
}, function (reason) {
|
||||
});
|
||||
```
|
||||
|
||||
The ``outputPromise`` variable becomes a new promise for the return
|
||||
value of either handler. Since a function can only either return a
|
||||
value or throw an exception, only one handler will ever be called and it
|
||||
will be responsible for resolving ``outputPromise``.
|
||||
|
||||
- If you return a value in a handler, ``outputPromise`` will get
|
||||
fulfilled.
|
||||
|
||||
- If you throw an exception in a handler, ``outputPromise`` will get
|
||||
rejected.
|
||||
|
||||
- If you return a **promise** in a handler, ``outputPromise`` will
|
||||
“become” that promise. Being able to become a new promise is useful
|
||||
for managing delays, combining results, or recovering from errors.
|
||||
|
||||
If the ``getInputPromise()`` promise gets rejected and you omit the
|
||||
rejection handler, the **error** will go to ``outputPromise``:
|
||||
|
||||
```javascript
|
||||
var outputPromise = getInputPromise()
|
||||
.then(function (value) {
|
||||
});
|
||||
```
|
||||
|
||||
If the input promise gets fulfilled and you omit the fulfillment handler, the
|
||||
**value** will go to ``outputPromise``:
|
||||
|
||||
```javascript
|
||||
var outputPromise = getInputPromise()
|
||||
.then(null, function (error) {
|
||||
});
|
||||
```
|
||||
|
||||
Q promises provide a ``fail`` shorthand for ``then`` when you are only
|
||||
interested in handling the error:
|
||||
|
||||
```javascript
|
||||
var outputPromise = getInputPromise()
|
||||
.fail(function (error) {
|
||||
});
|
||||
```
|
||||
|
||||
If you are writing JavaScript for modern engines only or using
|
||||
CoffeeScript, you may use `catch` instead of `fail`.
|
||||
|
||||
Promises also have a ``fin`` function that is like a ``finally`` clause.
|
||||
The final handler gets called, with no arguments, when the promise
|
||||
returned by ``getInputPromise()`` either returns a value or throws an
|
||||
error. The value returned or error thrown by ``getInputPromise()``
|
||||
passes directly to ``outputPromise`` unless the final handler fails, and
|
||||
may be delayed if the final handler returns a promise.
|
||||
|
||||
```javascript
|
||||
var outputPromise = getInputPromise()
|
||||
.fin(function () {
|
||||
// close files, database connections, stop servers, conclude tests
|
||||
});
|
||||
```
|
||||
|
||||
- If the handler returns a value, the value is ignored
|
||||
- If the handler throws an error, the error passes to ``outputPromise``
|
||||
- If the handler returns a promise, ``outputPromise`` gets postponed. The
|
||||
eventual value or error has the same effect as an immediate return
|
||||
value or thrown error: a value would be ignored, an error would be
|
||||
forwarded.
|
||||
|
||||
If you are writing JavaScript for modern engines only or using
|
||||
CoffeeScript, you may use `finally` instead of `fin`.
|
||||
|
||||
### Chaining
|
||||
|
||||
There are two ways to chain promises. You can chain promises either
|
||||
inside or outside handlers. The next two examples are equivalent.
|
||||
|
||||
```javascript
|
||||
return getUsername()
|
||||
.then(function (username) {
|
||||
return getUser(username)
|
||||
.then(function (user) {
|
||||
// if we get here without an error,
|
||||
// the value returned here
|
||||
// or the exception thrown here
|
||||
// resolves the promise returned
|
||||
// by the first line
|
||||
})
|
||||
});
|
||||
```
|
||||
|
||||
```javascript
|
||||
return getUsername()
|
||||
.then(function (username) {
|
||||
return getUser(username);
|
||||
})
|
||||
.then(function (user) {
|
||||
// if we get here without an error,
|
||||
// the value returned here
|
||||
// or the exception thrown here
|
||||
// resolves the promise returned
|
||||
// by the first line
|
||||
});
|
||||
```
|
||||
|
||||
The only difference is nesting. It’s useful to nest handlers if you
|
||||
need to capture multiple input values in your closure.
|
||||
|
||||
```javascript
|
||||
function authenticate() {
|
||||
return getUsername()
|
||||
.then(function (username) {
|
||||
return getUser(username);
|
||||
})
|
||||
// chained because we will not need the user name in the next event
|
||||
.then(function (user) {
|
||||
return getPassword()
|
||||
// nested because we need both user and password next
|
||||
.then(function (password) {
|
||||
if (user.passwordHash !== hash(password)) {
|
||||
throw new Error("Can't authenticate");
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### Combination
|
||||
|
||||
You can turn an array of promises into a promise for the whole,
|
||||
fulfilled array using ``all``.
|
||||
|
||||
```javascript
|
||||
return Q.all([
|
||||
eventualAdd(2, 2),
|
||||
eventualAdd(10, 20)
|
||||
]);
|
||||
```
|
||||
|
||||
If you have a promise for an array, you can use ``spread`` as a
|
||||
replacement for ``then``. The ``spread`` function “spreads” the
|
||||
values over the arguments of the fulfillment handler. The rejection handler
|
||||
will get called at the first sign of failure. That is, whichever of
|
||||
the recived promises fails first gets handled by the rejection handler.
|
||||
|
||||
```javascript
|
||||
function eventualAdd(a, b) {
|
||||
return Q.spread([a, b], function (a, b) {
|
||||
return a + b;
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
But ``spread`` calls ``all`` initially, so you can skip it in chains.
|
||||
|
||||
```javascript
|
||||
return getUsername()
|
||||
.then(function (username) {
|
||||
return [username, getUser(username)];
|
||||
})
|
||||
.spread(function (username, user) {
|
||||
});
|
||||
```
|
||||
|
||||
The ``all`` function returns a promise for an array of values. When this
|
||||
promise is fulfilled, the array contains the fulfillment values of the original
|
||||
promises, in the same order as those promises. If one of the given promises
|
||||
is rejected, the returned promise is immediately rejected, not waiting for the
|
||||
rest of the batch. If you want to wait for all of the promises to either be
|
||||
fulfilled or rejected, you can use ``allSettled``.
|
||||
|
||||
```javascript
|
||||
Q.allSettled(promises)
|
||||
.then(function (results) {
|
||||
results.forEach(function (result) {
|
||||
if (result.state === "fulfilled") {
|
||||
var value = result.value;
|
||||
} else {
|
||||
var reason = result.reason;
|
||||
}
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
|
||||
### Sequences
|
||||
|
||||
If you have a number of promise-producing functions that need
|
||||
to be run sequentially, you can of course do so manually:
|
||||
|
||||
```javascript
|
||||
return foo(initialVal).then(bar).then(baz).then(qux);
|
||||
```
|
||||
|
||||
However, if you want to run a dynamically constructed sequence of
|
||||
functions, you'll want something like this:
|
||||
|
||||
```javascript
|
||||
var funcs = [foo, bar, baz, qux];
|
||||
|
||||
var result = Q(initialVal);
|
||||
funcs.forEach(function (f) {
|
||||
result = result.then(f);
|
||||
});
|
||||
return result;
|
||||
```
|
||||
|
||||
You can make this slightly more compact using `reduce`:
|
||||
|
||||
```javascript
|
||||
return funcs.reduce(function (soFar, f) {
|
||||
return soFar.then(f);
|
||||
}, Q(initialVal));
|
||||
```
|
||||
|
||||
Or, you could use th ultra-compact version:
|
||||
|
||||
```javascript
|
||||
return funcs.reduce(Q.when, Q());
|
||||
```
|
||||
|
||||
### Handling Errors
|
||||
|
||||
One sometimes-unintuive aspect of promises is that if you throw an
|
||||
exception in the fulfillment handler, it will not be be caught by the error
|
||||
handler.
|
||||
|
||||
```javascript
|
||||
return foo()
|
||||
.then(function (value) {
|
||||
throw new Error("Can't bar.");
|
||||
}, function (error) {
|
||||
// We only get here if "foo" fails
|
||||
});
|
||||
```
|
||||
|
||||
To see why this is, consider the parallel between promises and
|
||||
``try``/``catch``. We are ``try``-ing to execute ``foo()``: the error
|
||||
handler represents a ``catch`` for ``foo()``, while the fulfillment handler
|
||||
represents code that happens *after* the ``try``/``catch`` block.
|
||||
That code then needs its own ``try``/``catch`` block.
|
||||
|
||||
In terms of promises, this means chaining your rejection handler:
|
||||
|
||||
```javascript
|
||||
return foo()
|
||||
.then(function (value) {
|
||||
throw new Error("Can't bar.");
|
||||
})
|
||||
.fail(function (error) {
|
||||
// We get here with either foo's error or bar's error
|
||||
});
|
||||
```
|
||||
|
||||
### Progress Notification
|
||||
|
||||
It's possible for promises to report their progress, e.g. for tasks that take a
|
||||
long time like a file upload. Not all promises will implement progress
|
||||
notifications, but for those that do, you can consume the progress values using
|
||||
a third parameter to ``then``:
|
||||
|
||||
```javascript
|
||||
return uploadFile()
|
||||
.then(function () {
|
||||
// Success uploading the file
|
||||
}, function (err) {
|
||||
// There was an error, and we get the reason for error
|
||||
}, function (progress) {
|
||||
// We get notified of the upload's progress as it is executed
|
||||
});
|
||||
```
|
||||
|
||||
Like `fail`, Q also provides a shorthand for progress callbacks
|
||||
called `progress`:
|
||||
|
||||
```javascript
|
||||
return uploadFile().progress(function (progress) {
|
||||
// We get notified of the upload's progress
|
||||
});
|
||||
```
|
||||
|
||||
### The End
|
||||
|
||||
When you get to the end of a chain of promises, you should either
|
||||
return the last promise or end the chain. Since handlers catch
|
||||
errors, it’s an unfortunate pattern that the exceptions can go
|
||||
unobserved.
|
||||
|
||||
So, either return it,
|
||||
|
||||
```javascript
|
||||
return foo()
|
||||
.then(function () {
|
||||
return "bar";
|
||||
});
|
||||
```
|
||||
|
||||
Or, end it.
|
||||
|
||||
```javascript
|
||||
foo()
|
||||
.then(function () {
|
||||
return "bar";
|
||||
})
|
||||
.done();
|
||||
```
|
||||
|
||||
Ending a promise chain makes sure that, if an error doesn’t get
|
||||
handled before the end, it will get rethrown and reported.
|
||||
|
||||
This is a stopgap. We are exploring ways to make unhandled errors
|
||||
visible without any explicit handling.
|
||||
|
||||
|
||||
### The Beginning
|
||||
|
||||
Everything above assumes you get a promise from somewhere else. This
|
||||
is the common case. Every once in a while, you will need to create a
|
||||
promise from scratch.
|
||||
|
||||
#### Using ``Q.fcall``
|
||||
|
||||
You can create a promise from a value using ``Q.fcall``. This returns a
|
||||
promise for 10.
|
||||
|
||||
```javascript
|
||||
return Q.fcall(function () {
|
||||
return 10;
|
||||
});
|
||||
```
|
||||
|
||||
You can also use ``fcall`` to get a promise for an exception.
|
||||
|
||||
```javascript
|
||||
return Q.fcall(function () {
|
||||
throw new Error("Can't do it");
|
||||
});
|
||||
```
|
||||
|
||||
As the name implies, ``fcall`` can call functions, or even promised
|
||||
functions. This uses the ``eventualAdd`` function above to add two
|
||||
numbers.
|
||||
|
||||
```javascript
|
||||
return Q.fcall(eventualAdd, 2, 2);
|
||||
```
|
||||
|
||||
|
||||
#### Using Deferreds
|
||||
|
||||
If you have to interface with asynchronous functions that are callback-based
|
||||
instead of promise-based, Q provides a few shortcuts (like ``Q.nfcall`` and
|
||||
friends). But much of the time, the solution will be to use *deferreds*.
|
||||
|
||||
```javascript
|
||||
var deferred = Q.defer();
|
||||
FS.readFile("foo.txt", "utf-8", function (error, text) {
|
||||
if (error) {
|
||||
deferred.reject(new Error(error));
|
||||
} else {
|
||||
deferred.resolve(text);
|
||||
}
|
||||
});
|
||||
return deferred.promise;
|
||||
```
|
||||
|
||||
Note that a deferred can be resolved with a value or a promise. The
|
||||
``reject`` function is a shorthand for resolving with a rejected
|
||||
promise.
|
||||
|
||||
```javascript
|
||||
// this:
|
||||
deferred.reject(new Error("Can't do it"));
|
||||
|
||||
// is shorthand for:
|
||||
var rejection = Q.fcall(function () {
|
||||
throw new Error("Can't do it");
|
||||
});
|
||||
deferred.resolve(rejection);
|
||||
```
|
||||
|
||||
This is a simplified implementation of ``Q.delay``.
|
||||
|
||||
```javascript
|
||||
function delay(ms) {
|
||||
var deferred = Q.defer();
|
||||
setTimeout(deferred.resolve, ms);
|
||||
return deferred.promise;
|
||||
}
|
||||
```
|
||||
|
||||
This is a simplified implementation of ``Q.timeout``
|
||||
|
||||
```javascript
|
||||
function timeout(promise, ms) {
|
||||
var deferred = Q.defer();
|
||||
Q.when(promise, deferred.resolve);
|
||||
delay(ms).then(function () {
|
||||
deferred.reject(new Error("Timed out"));
|
||||
});
|
||||
return deferred.promise;
|
||||
}
|
||||
```
|
||||
|
||||
Finally, you can send a progress notification to the promise with
|
||||
``deferred.notify``.
|
||||
|
||||
For illustration, this is a wrapper for XML HTTP requests in the browser. Note
|
||||
that a more [thorough][XHR] implementation would be in order in practice.
|
||||
|
||||
[XHR]: https://github.com/montagejs/mr/blob/71e8df99bb4f0584985accd6f2801ef3015b9763/browser.js#L29-L73
|
||||
|
||||
```javascript
|
||||
function requestOkText(url) {
|
||||
var request = new XMLHttpRequest();
|
||||
var deferred = Q.defer();
|
||||
|
||||
request.open("GET", url, true);
|
||||
request.onload = onload;
|
||||
request.onerror = onerror;
|
||||
request.onprogress = onprogress;
|
||||
request.send();
|
||||
|
||||
function onload() {
|
||||
if (request.status === 200) {
|
||||
deferred.resolve(request.responseText);
|
||||
} else {
|
||||
deferred.reject(new Error("Status code was " + request.status));
|
||||
}
|
||||
}
|
||||
|
||||
function onerror() {
|
||||
deferred.reject(new Error("Can't XHR " + JSON.stringify(url)));
|
||||
}
|
||||
|
||||
function onprogress(event) {
|
||||
deferred.notify(event.loaded / event.total);
|
||||
}
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
```
|
||||
|
||||
Below is an example of how to use this ``requestOkText`` function:
|
||||
|
||||
```javascript
|
||||
requestOkText("http://localhost:3000")
|
||||
.then(function (responseText) {
|
||||
// If the HTTP response returns 200 OK, log the response text.
|
||||
console.log(responseText);
|
||||
}, function (error) {
|
||||
// If there's an error or a non-200 status code, log the error.
|
||||
console.error(error);
|
||||
}, function (progress) {
|
||||
// Log the progress as it comes in.
|
||||
console.log("Request progress: " + Math.round(progress * 100) + "%");
|
||||
});
|
||||
```
|
||||
|
||||
### The Middle
|
||||
|
||||
If you are using a function that may return a promise, but just might
|
||||
return a value if it doesn’t need to defer, you can use the “static”
|
||||
methods of the Q library.
|
||||
|
||||
The ``when`` function is the static equivalent for ``then``.
|
||||
|
||||
```javascript
|
||||
return Q.when(valueOrPromise, function (value) {
|
||||
}, function (error) {
|
||||
});
|
||||
```
|
||||
|
||||
All of the other methods on a promise have static analogs with the
|
||||
same name.
|
||||
|
||||
The following are equivalent:
|
||||
|
||||
```javascript
|
||||
return Q.all([a, b]);
|
||||
```
|
||||
|
||||
```javascript
|
||||
return Q.fcall(function () {
|
||||
return [a, b];
|
||||
})
|
||||
.all();
|
||||
```
|
||||
|
||||
When working with promises provided by other libraries, you should
|
||||
convert it to a Q promise. Not all promise libraries make the same
|
||||
guarantees as Q and certainly don’t provide all of the same methods.
|
||||
Most libraries only provide a partially functional ``then`` method.
|
||||
This thankfully is all we need to turn them into vibrant Q promises.
|
||||
|
||||
```javascript
|
||||
return Q($.ajax(...))
|
||||
.then(function () {
|
||||
});
|
||||
```
|
||||
|
||||
If there is any chance that the promise you receive is not a Q promise
|
||||
as provided by your library, you should wrap it using a Q function.
|
||||
You can even use ``Q.invoke`` as a shorthand.
|
||||
|
||||
```javascript
|
||||
return Q.invoke($, 'ajax', ...)
|
||||
.then(function () {
|
||||
});
|
||||
```
|
||||
|
||||
|
||||
### Over the Wire
|
||||
|
||||
A promise can serve as a proxy for another object, even a remote
|
||||
object. There are methods that allow you to optimistically manipulate
|
||||
properties or call functions. All of these interactions return
|
||||
promises, so they can be chained.
|
||||
|
||||
```
|
||||
direct manipulation using a promise as a proxy
|
||||
-------------------------- -------------------------------
|
||||
value.foo promise.get("foo")
|
||||
value.foo = value promise.put("foo", value)
|
||||
delete value.foo promise.del("foo")
|
||||
value.foo(...args) promise.post("foo", [args])
|
||||
value.foo(...args) promise.invoke("foo", ...args)
|
||||
value(...args) promise.fapply([args])
|
||||
value(...args) promise.fcall(...args)
|
||||
```
|
||||
|
||||
If the promise is a proxy for a remote object, you can shave
|
||||
round-trips by using these functions instead of ``then``. To take
|
||||
advantage of promises for remote objects, check out [Q-Connection][].
|
||||
|
||||
[Q-Connection]: https://github.com/kriskowal/q-connection
|
||||
|
||||
Even in the case of non-remote objects, these methods can be used as
|
||||
shorthand for particularly-simple fulfillment handlers. For example, you
|
||||
can replace
|
||||
|
||||
```javascript
|
||||
return Q.fcall(function () {
|
||||
return [{ foo: "bar" }, { foo: "baz" }];
|
||||
})
|
||||
.then(function (value) {
|
||||
return value[0].foo;
|
||||
});
|
||||
```
|
||||
|
||||
with
|
||||
|
||||
```javascript
|
||||
return Q.fcall(function () {
|
||||
return [{ foo: "bar" }, { foo: "baz" }];
|
||||
})
|
||||
.get(0)
|
||||
.get("foo");
|
||||
```
|
||||
|
||||
|
||||
### Adapting Node
|
||||
|
||||
If you're working with functions that make use of the Node.js callback pattern,
|
||||
where callbacks are in the form of `function(err, result)`, Q provides a few
|
||||
useful utility functions for converting between them. The most straightforward
|
||||
are probably `Q.nfcall` and `Q.nfapply` ("Node function call/apply") for calling
|
||||
Node.js-style functions and getting back a promise:
|
||||
|
||||
```javascript
|
||||
return Q.nfcall(FS.readFile, "foo.txt", "utf-8");
|
||||
return Q.nfapply(FS.readFile, ["foo.txt", "utf-8"]);
|
||||
```
|
||||
|
||||
If you are working with methods, instead of simple functions, you can easily
|
||||
run in to the usual problems where passing a method to another function—like
|
||||
`Q.nfcall`—"un-binds" the method from its owner. To avoid this, you can either
|
||||
use `Function.prototype.bind` or some nice shortcut methods we provide:
|
||||
|
||||
```javascript
|
||||
return Q.ninvoke(redisClient, "get", "user:1:id");
|
||||
return Q.npost(redisClient, "get", ["user:1:id"]);
|
||||
```
|
||||
|
||||
You can also create reusable wrappers with `Q.denodeify` or `Q.nbind`:
|
||||
|
||||
```javascript
|
||||
var readFile = Q.denodeify(FS.readFile);
|
||||
return readFile("foo.txt", "utf-8");
|
||||
|
||||
var redisClientGet = Q.nbind(redisClient.get, redisClient);
|
||||
return redisClientGet("user:1:id");
|
||||
```
|
||||
|
||||
Finally, if you're working with raw deferred objects, there is a
|
||||
`makeNodeResolver` method on deferreds that can be handy:
|
||||
|
||||
```javascript
|
||||
var deferred = Q.defer();
|
||||
FS.readFile("foo.txt", "utf-8", deferred.makeNodeResolver());
|
||||
return deferred.promise;
|
||||
```
|
||||
|
||||
### Long Stack Traces
|
||||
|
||||
Q comes with optional support for “long stack traces,” wherein the `stack`
|
||||
property of `Error` rejection reasons is rewritten to be traced along
|
||||
asynchronous jumps instead of stopping at the most recent one. As an example:
|
||||
|
||||
```js
|
||||
function theDepthsOfMyProgram() {
|
||||
Q.delay(100).done(function explode() {
|
||||
throw new Error("boo!");
|
||||
});
|
||||
}
|
||||
|
||||
theDepthsOfMyProgram();
|
||||
```
|
||||
|
||||
usually would give a rather unhelpful stack trace looking something like
|
||||
|
||||
```
|
||||
Error: boo!
|
||||
at explode (/path/to/test.js:3:11)
|
||||
at _fulfilled (/path/to/test.js:q:54)
|
||||
at resolvedValue.promiseDispatch.done (/path/to/q.js:823:30)
|
||||
at makePromise.promise.promiseDispatch (/path/to/q.js:496:13)
|
||||
at pending (/path/to/q.js:397:39)
|
||||
at process.startup.processNextTick.process._tickCallback (node.js:244:9)
|
||||
```
|
||||
|
||||
But, if you turn this feature on by setting
|
||||
|
||||
```js
|
||||
Q.longStackSupport = true;
|
||||
```
|
||||
|
||||
then the above code gives a nice stack trace to the tune of
|
||||
|
||||
```
|
||||
Error: boo!
|
||||
at explode (/path/to/test.js:3:11)
|
||||
From previous event:
|
||||
at theDepthsOfMyProgram (/path/to/test.js:2:16)
|
||||
at Object.<anonymous> (/path/to/test.js:7:1)
|
||||
```
|
||||
|
||||
Note how you can see the the function that triggered the async operation in the
|
||||
stack trace! This is very helpful for debugging, as otherwise you end up getting
|
||||
only the first line, plus a bunch of Q internals, with no sign of where the
|
||||
operation started.
|
||||
|
||||
This feature does come with somewhat-serious performance and memory overhead,
|
||||
however. If you're working with lots of promises, or trying to scale a server
|
||||
to many users, you should probably keep it off. But in development, go for it!
|
||||
|
||||
## Tests
|
||||
|
||||
You can view the results of the Q test suite [in your browser][tests]!
|
||||
|
||||
[tests]: https://rawgithub.com/kriskowal/q/master/spec/q-spec.html
|
||||
|
||||
## License
|
||||
|
||||
Copyright 2009–2013 Kristopher Michael Kowal
|
||||
MIT License (enclosed)
|
||||
|
||||
71
bin/node_modules/q/benchmark/compare-with-callbacks.js
generated
vendored
Normal file
71
bin/node_modules/q/benchmark/compare-with-callbacks.js
generated
vendored
Normal file
@@ -0,0 +1,71 @@
|
||||
"use strict";
|
||||
|
||||
var Q = require("../q");
|
||||
var fs = require("fs");
|
||||
|
||||
suite("A single simple async operation", function () {
|
||||
bench("with an immediately-fulfilled promise", function (done) {
|
||||
Q().then(done);
|
||||
});
|
||||
|
||||
bench("with direct setImmediate usage", function (done) {
|
||||
setImmediate(done);
|
||||
});
|
||||
|
||||
bench("with direct setTimeout(…, 0)", function (done) {
|
||||
setTimeout(done, 0);
|
||||
});
|
||||
});
|
||||
|
||||
suite("A fs.readFile", function () {
|
||||
var denodeified = Q.denodeify(fs.readFile);
|
||||
|
||||
set("iterations", 1000);
|
||||
set("delay", 1000);
|
||||
|
||||
bench("directly, with callbacks", function (done) {
|
||||
fs.readFile(__filename, done);
|
||||
});
|
||||
|
||||
bench("with Q.nfcall", function (done) {
|
||||
Q.nfcall(fs.readFile, __filename).then(done);
|
||||
});
|
||||
|
||||
bench("with a Q.denodeify'ed version", function (done) {
|
||||
denodeified(__filename).then(done);
|
||||
});
|
||||
|
||||
bench("with manual usage of deferred.makeNodeResolver", function (done) {
|
||||
var deferred = Q.defer();
|
||||
fs.readFile(__filename, deferred.makeNodeResolver());
|
||||
deferred.promise.then(done);
|
||||
});
|
||||
});
|
||||
|
||||
suite("1000 operations in parallel", function () {
|
||||
function makeCounter(desiredCount, ultimateCallback) {
|
||||
var soFar = 0;
|
||||
return function () {
|
||||
if (++soFar === desiredCount) {
|
||||
ultimateCallback();
|
||||
}
|
||||
};
|
||||
}
|
||||
var numberOfOps = 1000;
|
||||
|
||||
bench("with immediately-fulfilled promises", function (done) {
|
||||
var counter = makeCounter(numberOfOps, done);
|
||||
|
||||
for (var i = 0; i < numberOfOps; ++i) {
|
||||
Q().then(counter);
|
||||
}
|
||||
});
|
||||
|
||||
bench("with direct setImmediate usage", function (done) {
|
||||
var counter = makeCounter(numberOfOps, done);
|
||||
|
||||
for (var i = 0; i < numberOfOps; ++i) {
|
||||
setImmediate(counter);
|
||||
}
|
||||
});
|
||||
});
|
||||
36
bin/node_modules/q/benchmark/scenarios.js
generated
vendored
Normal file
36
bin/node_modules/q/benchmark/scenarios.js
generated
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
"use strict";
|
||||
|
||||
var Q = require("../q");
|
||||
|
||||
suite("Chaining", function () {
|
||||
var numberToChain = 1000;
|
||||
|
||||
bench("Chaining many already-fulfilled promises together", function (done) {
|
||||
var currentPromise = Q();
|
||||
for (var i = 0; i < numberToChain; ++i) {
|
||||
currentPromise = currentPromise.then(function () {
|
||||
return Q();
|
||||
});
|
||||
}
|
||||
|
||||
currentPromise.then(done);
|
||||
});
|
||||
|
||||
bench("Chaining and then fulfilling the end of the chain", function (done) {
|
||||
var deferred = Q.defer();
|
||||
|
||||
var currentPromise = deferred.promise;
|
||||
for (var i = 0; i < numberToChain; ++i) {
|
||||
(function () {
|
||||
var promiseToReturn = currentPromise;
|
||||
currentPromise = Q().then(function () {
|
||||
return promiseToReturn;
|
||||
});
|
||||
}());
|
||||
}
|
||||
|
||||
currentPromise.then(done);
|
||||
|
||||
deferred.resolve();
|
||||
});
|
||||
});
|
||||
93
bin/node_modules/q/package.json
generated
vendored
Normal file
93
bin/node_modules/q/package.json
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
1937
bin/node_modules/q/q.js
generated
vendored
Normal file
1937
bin/node_modules/q/q.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
35
bin/node_modules/q/queue.js
generated
vendored
Normal file
35
bin/node_modules/q/queue.js
generated
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
|
||||
var Q = require("./q");
|
||||
|
||||
module.exports = Queue;
|
||||
function Queue() {
|
||||
var ends = Q.defer();
|
||||
var closed = Q.defer();
|
||||
return {
|
||||
put: function (value) {
|
||||
var next = Q.defer();
|
||||
ends.resolve({
|
||||
head: value,
|
||||
tail: next.promise
|
||||
});
|
||||
ends.resolve = next.resolve;
|
||||
},
|
||||
get: function () {
|
||||
var result = ends.promise.get("head");
|
||||
ends.promise = ends.promise.get("tail");
|
||||
return result.fail(function (error) {
|
||||
closed.resolve(error);
|
||||
throw error;
|
||||
});
|
||||
},
|
||||
closed: closed.promise,
|
||||
close: function (error) {
|
||||
error = error || new Error("Can't get value from closed queue");
|
||||
var end = {head: Q.reject(error)};
|
||||
end.tail = end;
|
||||
ends.resolve(end);
|
||||
return closed.promise;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
6
bin/node_modules/shelljs/.documentup.json
generated
vendored
Normal file
6
bin/node_modules/shelljs/.documentup.json
generated
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"name": "ShellJS",
|
||||
"twitter": [
|
||||
"r2r"
|
||||
]
|
||||
}
|
||||
7
bin/node_modules/shelljs/.jshintrc
generated
vendored
Normal file
7
bin/node_modules/shelljs/.jshintrc
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"loopfunc": true,
|
||||
"sub": true,
|
||||
"undef": true,
|
||||
"unused": true,
|
||||
"node": true
|
||||
}
|
||||
2
bin/node_modules/shelljs/.npmignore
generated
vendored
Normal file
2
bin/node_modules/shelljs/.npmignore
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
test/
|
||||
tmp/
|
||||
5
bin/node_modules/shelljs/.travis.yml
generated
vendored
Normal file
5
bin/node_modules/shelljs/.travis.yml
generated
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
language: node_js
|
||||
node_js:
|
||||
- "0.8"
|
||||
- "0.10"
|
||||
- "0.11"
|
||||
26
bin/node_modules/shelljs/LICENSE
generated
vendored
Normal file
26
bin/node_modules/shelljs/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
Copyright (c) 2012, Artur Adib <aadib@mozilla.com>
|
||||
All rights reserved.
|
||||
|
||||
You may use this project under the terms of the New BSD license as follows:
|
||||
|
||||
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 Artur Adib nor the
|
||||
names of the 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 ARTUR ADIB 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.
|
||||
552
bin/node_modules/shelljs/README.md
generated
vendored
Normal file
552
bin/node_modules/shelljs/README.md
generated
vendored
Normal file
@@ -0,0 +1,552 @@
|
||||
# ShellJS - Unix shell commands for Node.js [](http://travis-ci.org/arturadib/shelljs)
|
||||
|
||||
ShellJS is a portable **(Windows/Linux/OS X)** implementation of Unix shell commands on top of the Node.js API. You can use it to eliminate your shell script's dependency on Unix while still keeping its familiar and powerful commands. You can also install it globally so you can run it from outside Node projects - say goodbye to those gnarly Bash scripts!
|
||||
|
||||
The project is [unit-tested](http://travis-ci.org/arturadib/shelljs) and battled-tested in projects like:
|
||||
|
||||
+ [PDF.js](http://github.com/mozilla/pdf.js) - Firefox's next-gen PDF reader
|
||||
+ [Firebug](http://getfirebug.com/) - Firefox's infamous debugger
|
||||
+ [JSHint](http://jshint.com) - Most popular JavaScript linter
|
||||
+ [Zepto](http://zeptojs.com) - jQuery-compatible JavaScript library for modern browsers
|
||||
+ [Yeoman](http://yeoman.io/) - Web application stack and development tool
|
||||
+ [Deployd.com](http://deployd.com) - Open source PaaS for quick API backend generation
|
||||
|
||||
and [many more](https://npmjs.org/browse/depended/shelljs).
|
||||
|
||||
## Installing
|
||||
|
||||
Via npm:
|
||||
|
||||
```bash
|
||||
$ npm install [-g] shelljs
|
||||
```
|
||||
|
||||
If the global option `-g` is specified, the binary `shjs` will be installed. This makes it possible to
|
||||
run ShellJS scripts much like any shell script from the command line, i.e. without requiring a `node_modules` folder:
|
||||
|
||||
```bash
|
||||
$ shjs my_script
|
||||
```
|
||||
|
||||
You can also just copy `shell.js` into your project's directory, and `require()` accordingly.
|
||||
|
||||
|
||||
## Examples
|
||||
|
||||
### JavaScript
|
||||
|
||||
```javascript
|
||||
require('shelljs/global');
|
||||
|
||||
if (!which('git')) {
|
||||
echo('Sorry, this script requires git');
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Copy files to release dir
|
||||
mkdir('-p', 'out/Release');
|
||||
cp('-R', 'stuff/*', 'out/Release');
|
||||
|
||||
// Replace macros in each .js file
|
||||
cd('lib');
|
||||
ls('*.js').forEach(function(file) {
|
||||
sed('-i', 'BUILD_VERSION', 'v0.1.2', file);
|
||||
sed('-i', /.*REMOVE_THIS_LINE.*\n/, '', file);
|
||||
sed('-i', /.*REPLACE_LINE_WITH_MACRO.*\n/, cat('macro.js'), file);
|
||||
});
|
||||
cd('..');
|
||||
|
||||
// Run external tool synchronously
|
||||
if (exec('git commit -am "Auto-commit"').code !== 0) {
|
||||
echo('Error: Git commit failed');
|
||||
exit(1);
|
||||
}
|
||||
```
|
||||
|
||||
### CoffeeScript
|
||||
|
||||
```coffeescript
|
||||
require 'shelljs/global'
|
||||
|
||||
if not which 'git'
|
||||
echo 'Sorry, this script requires git'
|
||||
exit 1
|
||||
|
||||
# Copy files to release dir
|
||||
mkdir '-p', 'out/Release'
|
||||
cp '-R', 'stuff/*', 'out/Release'
|
||||
|
||||
# Replace macros in each .js file
|
||||
cd 'lib'
|
||||
for file in ls '*.js'
|
||||
sed '-i', 'BUILD_VERSION', 'v0.1.2', file
|
||||
sed '-i', /.*REMOVE_THIS_LINE.*\n/, '', file
|
||||
sed '-i', /.*REPLACE_LINE_WITH_MACRO.*\n/, cat 'macro.js', file
|
||||
cd '..'
|
||||
|
||||
# Run external tool synchronously
|
||||
if (exec 'git commit -am "Auto-commit"').code != 0
|
||||
echo 'Error: Git commit failed'
|
||||
exit 1
|
||||
```
|
||||
|
||||
## Global vs. Local
|
||||
|
||||
The example above uses the convenience script `shelljs/global` to reduce verbosity. If polluting your global namespace is not desirable, simply require `shelljs`.
|
||||
|
||||
Example:
|
||||
|
||||
```javascript
|
||||
var shell = require('shelljs');
|
||||
shell.echo('hello world');
|
||||
```
|
||||
|
||||
## Make tool
|
||||
|
||||
A convenience script `shelljs/make` is also provided to mimic the behavior of a Unix Makefile. In this case all shell objects are global, and command line arguments will cause the script to execute only the corresponding function in the global `target` object. To avoid redundant calls, target functions are executed only once per script.
|
||||
|
||||
Example (CoffeeScript):
|
||||
|
||||
```coffeescript
|
||||
require 'shelljs/make'
|
||||
|
||||
target.all = ->
|
||||
target.bundle()
|
||||
target.docs()
|
||||
|
||||
target.bundle = ->
|
||||
cd __dirname
|
||||
mkdir 'build'
|
||||
cd 'lib'
|
||||
(cat '*.js').to '../build/output.js'
|
||||
|
||||
target.docs = ->
|
||||
cd __dirname
|
||||
mkdir 'docs'
|
||||
cd 'lib'
|
||||
for file in ls '*.js'
|
||||
text = grep '//@', file # extract special comments
|
||||
text.replace '//@', '' # remove comment tags
|
||||
text.to 'docs/my_docs.md'
|
||||
```
|
||||
|
||||
To run the target `all`, call the above script without arguments: `$ node make`. To run the target `docs`: `$ node make docs`, and so on.
|
||||
|
||||
|
||||
|
||||
<!--
|
||||
|
||||
DO NOT MODIFY BEYOND THIS POINT - IT'S AUTOMATICALLY GENERATED
|
||||
|
||||
-->
|
||||
|
||||
|
||||
## Command reference
|
||||
|
||||
|
||||
All commands run synchronously, unless otherwise stated.
|
||||
|
||||
|
||||
### cd('dir')
|
||||
Changes to directory `dir` for the duration of the script
|
||||
|
||||
|
||||
### pwd()
|
||||
Returns the current directory.
|
||||
|
||||
|
||||
### ls([options ,] path [,path ...])
|
||||
### ls([options ,] path_array)
|
||||
Available options:
|
||||
|
||||
+ `-R`: recursive
|
||||
+ `-A`: all files (include files beginning with `.`, except for `.` and `..`)
|
||||
|
||||
Examples:
|
||||
|
||||
```javascript
|
||||
ls('projs/*.js');
|
||||
ls('-R', '/users/me', '/tmp');
|
||||
ls('-R', ['/users/me', '/tmp']); // same as above
|
||||
```
|
||||
|
||||
Returns array of files in the given path, or in current directory if no path provided.
|
||||
|
||||
|
||||
### find(path [,path ...])
|
||||
### find(path_array)
|
||||
Examples:
|
||||
|
||||
```javascript
|
||||
find('src', 'lib');
|
||||
find(['src', 'lib']); // same as above
|
||||
find('.').filter(function(file) { return file.match(/\.js$/); });
|
||||
```
|
||||
|
||||
Returns array of all files (however deep) in the given paths.
|
||||
|
||||
The main difference from `ls('-R', path)` is that the resulting file names
|
||||
include the base directories, e.g. `lib/resources/file1` instead of just `file1`.
|
||||
|
||||
|
||||
### cp([options ,] source [,source ...], dest)
|
||||
### cp([options ,] source_array, dest)
|
||||
Available options:
|
||||
|
||||
+ `-f`: force
|
||||
+ `-r, -R`: recursive
|
||||
|
||||
Examples:
|
||||
|
||||
```javascript
|
||||
cp('file1', 'dir1');
|
||||
cp('-Rf', '/tmp/*', '/usr/local/*', '/home/tmp');
|
||||
cp('-Rf', ['/tmp/*', '/usr/local/*'], '/home/tmp'); // same as above
|
||||
```
|
||||
|
||||
Copies files. The wildcard `*` is accepted.
|
||||
|
||||
|
||||
### rm([options ,] file [, file ...])
|
||||
### rm([options ,] file_array)
|
||||
Available options:
|
||||
|
||||
+ `-f`: force
|
||||
+ `-r, -R`: recursive
|
||||
|
||||
Examples:
|
||||
|
||||
```javascript
|
||||
rm('-rf', '/tmp/*');
|
||||
rm('some_file.txt', 'another_file.txt');
|
||||
rm(['some_file.txt', 'another_file.txt']); // same as above
|
||||
```
|
||||
|
||||
Removes files. The wildcard `*` is accepted.
|
||||
|
||||
|
||||
### mv(source [, source ...], dest')
|
||||
### mv(source_array, dest')
|
||||
Available options:
|
||||
|
||||
+ `f`: force
|
||||
|
||||
Examples:
|
||||
|
||||
```javascript
|
||||
mv('-f', 'file', 'dir/');
|
||||
mv('file1', 'file2', 'dir/');
|
||||
mv(['file1', 'file2'], 'dir/'); // same as above
|
||||
```
|
||||
|
||||
Moves files. The wildcard `*` is accepted.
|
||||
|
||||
|
||||
### mkdir([options ,] dir [, dir ...])
|
||||
### mkdir([options ,] dir_array)
|
||||
Available options:
|
||||
|
||||
+ `p`: full path (will create intermediate dirs if necessary)
|
||||
|
||||
Examples:
|
||||
|
||||
```javascript
|
||||
mkdir('-p', '/tmp/a/b/c/d', '/tmp/e/f/g');
|
||||
mkdir('-p', ['/tmp/a/b/c/d', '/tmp/e/f/g']); // same as above
|
||||
```
|
||||
|
||||
Creates directories.
|
||||
|
||||
|
||||
### test(expression)
|
||||
Available expression primaries:
|
||||
|
||||
+ `'-b', 'path'`: true if path is a block device
|
||||
+ `'-c', 'path'`: true if path is a character device
|
||||
+ `'-d', 'path'`: true if path is a directory
|
||||
+ `'-e', 'path'`: true if path exists
|
||||
+ `'-f', 'path'`: true if path is a regular file
|
||||
+ `'-L', 'path'`: true if path is a symboilc link
|
||||
+ `'-p', 'path'`: true if path is a pipe (FIFO)
|
||||
+ `'-S', 'path'`: true if path is a socket
|
||||
|
||||
Examples:
|
||||
|
||||
```javascript
|
||||
if (test('-d', path)) { /* do something with dir */ };
|
||||
if (!test('-f', path)) continue; // skip if it's a regular file
|
||||
```
|
||||
|
||||
Evaluates expression using the available primaries and returns corresponding value.
|
||||
|
||||
|
||||
### cat(file [, file ...])
|
||||
### cat(file_array)
|
||||
|
||||
Examples:
|
||||
|
||||
```javascript
|
||||
var str = cat('file*.txt');
|
||||
var str = cat('file1', 'file2');
|
||||
var str = cat(['file1', 'file2']); // same as above
|
||||
```
|
||||
|
||||
Returns a string containing the given file, or a concatenated string
|
||||
containing the files if more than one file is given (a new line character is
|
||||
introduced between each file). Wildcard `*` accepted.
|
||||
|
||||
|
||||
### 'string'.to(file)
|
||||
|
||||
Examples:
|
||||
|
||||
```javascript
|
||||
cat('input.txt').to('output.txt');
|
||||
```
|
||||
|
||||
Analogous to the redirection operator `>` in Unix, but works with JavaScript strings (such as
|
||||
those returned by `cat`, `grep`, etc). _Like Unix redirections, `to()` will overwrite any existing file!_
|
||||
|
||||
|
||||
### 'string'.toEnd(file)
|
||||
|
||||
Examples:
|
||||
|
||||
```javascript
|
||||
cat('input.txt').toEnd('output.txt');
|
||||
```
|
||||
|
||||
Analogous to the redirect-and-append operator `>>` in Unix, but works with JavaScript strings (such as
|
||||
those returned by `cat`, `grep`, etc).
|
||||
|
||||
|
||||
### sed([options ,] search_regex, replace_str, file)
|
||||
Available options:
|
||||
|
||||
+ `-i`: Replace contents of 'file' in-place. _Note that no backups will be created!_
|
||||
|
||||
Examples:
|
||||
|
||||
```javascript
|
||||
sed('-i', 'PROGRAM_VERSION', 'v0.1.3', 'source.js');
|
||||
sed(/.*DELETE_THIS_LINE.*\n/, '', 'source.js');
|
||||
```
|
||||
|
||||
Reads an input string from `file` and performs a JavaScript `replace()` on the input
|
||||
using the given search regex and replacement string. Returns the new string after replacement.
|
||||
|
||||
|
||||
### grep([options ,] regex_filter, file [, file ...])
|
||||
### grep([options ,] regex_filter, file_array)
|
||||
Available options:
|
||||
|
||||
+ `-v`: Inverse the sense of the regex and print the lines not matching the criteria.
|
||||
|
||||
Examples:
|
||||
|
||||
```javascript
|
||||
grep('-v', 'GLOBAL_VARIABLE', '*.js');
|
||||
grep('GLOBAL_VARIABLE', '*.js');
|
||||
```
|
||||
|
||||
Reads input string from given files and returns a string containing all lines of the
|
||||
file that match the given `regex_filter`. Wildcard `*` accepted.
|
||||
|
||||
|
||||
### which(command)
|
||||
|
||||
Examples:
|
||||
|
||||
```javascript
|
||||
var nodeExec = which('node');
|
||||
```
|
||||
|
||||
Searches for `command` in the system's PATH. On Windows looks for `.exe`, `.cmd`, and `.bat` extensions.
|
||||
Returns string containing the absolute path to the command.
|
||||
|
||||
|
||||
### echo(string [,string ...])
|
||||
|
||||
Examples:
|
||||
|
||||
```javascript
|
||||
echo('hello world');
|
||||
var str = echo('hello world');
|
||||
```
|
||||
|
||||
Prints string to stdout, and returns string with additional utility methods
|
||||
like `.to()`.
|
||||
|
||||
|
||||
### pushd([options,] [dir | '-N' | '+N'])
|
||||
|
||||
Available options:
|
||||
|
||||
+ `-n`: Suppresses the normal change of directory when adding directories to the stack, so that only the stack is manipulated.
|
||||
|
||||
Arguments:
|
||||
|
||||
+ `dir`: Makes the current working directory be the top of the stack, and then executes the equivalent of `cd dir`.
|
||||
+ `+N`: Brings the Nth directory (counting from the left of the list printed by dirs, starting with zero) to the top of the list by rotating the stack.
|
||||
+ `-N`: Brings the Nth directory (counting from the right of the list printed by dirs, starting with zero) to the top of the list by rotating the stack.
|
||||
|
||||
Examples:
|
||||
|
||||
```javascript
|
||||
// process.cwd() === '/usr'
|
||||
pushd('/etc'); // Returns /etc /usr
|
||||
pushd('+1'); // Returns /usr /etc
|
||||
```
|
||||
|
||||
Save the current directory on the top of the directory stack and then cd to `dir`. With no arguments, pushd exchanges the top two directories. Returns an array of paths in the stack.
|
||||
|
||||
### popd([options,] ['-N' | '+N'])
|
||||
|
||||
Available options:
|
||||
|
||||
+ `-n`: Suppresses the normal change of directory when removing directories from the stack, so that only the stack is manipulated.
|
||||
|
||||
Arguments:
|
||||
|
||||
+ `+N`: Removes the Nth directory (counting from the left of the list printed by dirs), starting with zero.
|
||||
+ `-N`: Removes the Nth directory (counting from the right of the list printed by dirs), starting with zero.
|
||||
|
||||
Examples:
|
||||
|
||||
```javascript
|
||||
echo(process.cwd()); // '/usr'
|
||||
pushd('/etc'); // '/etc /usr'
|
||||
echo(process.cwd()); // '/etc'
|
||||
popd(); // '/usr'
|
||||
echo(process.cwd()); // '/usr'
|
||||
```
|
||||
|
||||
When no arguments are given, popd removes the top directory from the stack and performs a cd to the new top directory. The elements are numbered from 0 starting at the first directory listed with dirs; i.e., popd is equivalent to popd +0. Returns an array of paths in the stack.
|
||||
|
||||
### dirs([options | '+N' | '-N'])
|
||||
|
||||
Available options:
|
||||
|
||||
+ `-c`: Clears the directory stack by deleting all of the elements.
|
||||
|
||||
Arguments:
|
||||
|
||||
+ `+N`: Displays the Nth directory (counting from the left of the list printed by dirs when invoked without options), starting with zero.
|
||||
+ `-N`: Displays the Nth directory (counting from the right of the list printed by dirs when invoked without options), starting with zero.
|
||||
|
||||
Display the list of currently remembered directories. Returns an array of paths in the stack, or a single path if +N or -N was specified.
|
||||
|
||||
See also: pushd, popd
|
||||
|
||||
|
||||
### exit(code)
|
||||
Exits the current process with the given exit code.
|
||||
|
||||
### env['VAR_NAME']
|
||||
Object containing environment variables (both getter and setter). Shortcut to process.env.
|
||||
|
||||
### exec(command [, options] [, callback])
|
||||
Available options (all `false` by default):
|
||||
|
||||
+ `async`: Asynchronous execution. Defaults to true if a callback is provided.
|
||||
+ `silent`: Do not echo program output to console.
|
||||
|
||||
Examples:
|
||||
|
||||
```javascript
|
||||
var version = exec('node --version', {silent:true}).output;
|
||||
|
||||
var child = exec('some_long_running_process', {async:true});
|
||||
child.stdout.on('data', function(data) {
|
||||
/* ... do something with data ... */
|
||||
});
|
||||
|
||||
exec('some_long_running_process', function(code, output) {
|
||||
console.log('Exit code:', code);
|
||||
console.log('Program output:', output);
|
||||
});
|
||||
```
|
||||
|
||||
Executes the given `command` _synchronously_, unless otherwise specified.
|
||||
When in synchronous mode returns the object `{ code:..., output:... }`, containing the program's
|
||||
`output` (stdout + stderr) and its exit `code`. Otherwise returns the child process object, and
|
||||
the `callback` gets the arguments `(code, output)`.
|
||||
|
||||
**Note:** For long-lived processes, it's best to run `exec()` asynchronously as
|
||||
the current synchronous implementation uses a lot of CPU. This should be getting
|
||||
fixed soon.
|
||||
|
||||
|
||||
### chmod(octal_mode || octal_string, file)
|
||||
### chmod(symbolic_mode, file)
|
||||
|
||||
Available options:
|
||||
|
||||
+ `-v`: output a diagnostic for every file processed
|
||||
+ `-c`: like verbose but report only when a change is made
|
||||
+ `-R`: change files and directories recursively
|
||||
|
||||
Examples:
|
||||
|
||||
```javascript
|
||||
chmod(755, '/Users/brandon');
|
||||
chmod('755', '/Users/brandon'); // same as above
|
||||
chmod('u+x', '/Users/brandon');
|
||||
```
|
||||
|
||||
Alters the permissions of a file or directory by either specifying the
|
||||
absolute permissions in octal form or expressing the changes in symbols.
|
||||
This command tries to mimic the POSIX behavior as much as possible.
|
||||
Notable exceptions:
|
||||
|
||||
+ In symbolic modes, 'a-r' and '-r' are identical. No consideration is
|
||||
given to the umask.
|
||||
+ There is no "quiet" option since default behavior is to run silent.
|
||||
|
||||
|
||||
## Non-Unix commands
|
||||
|
||||
|
||||
### tempdir()
|
||||
|
||||
Examples:
|
||||
|
||||
```javascript
|
||||
var tmp = tempdir(); // "/tmp" for most *nix platforms
|
||||
```
|
||||
|
||||
Searches and returns string containing a writeable, platform-dependent temporary directory.
|
||||
Follows Python's [tempfile algorithm](http://docs.python.org/library/tempfile.html#tempfile.tempdir).
|
||||
|
||||
|
||||
### error()
|
||||
Tests if error occurred in the last command. Returns `null` if no error occurred,
|
||||
otherwise returns string explaining the error
|
||||
|
||||
|
||||
## Configuration
|
||||
|
||||
|
||||
### config.silent
|
||||
Example:
|
||||
|
||||
```javascript
|
||||
var silentState = config.silent; // save old silent state
|
||||
config.silent = true;
|
||||
/* ... */
|
||||
config.silent = silentState; // restore old silent state
|
||||
```
|
||||
|
||||
Suppresses all command output if `true`, except for `echo()` calls.
|
||||
Default is `false`.
|
||||
|
||||
### config.fatal
|
||||
Example:
|
||||
|
||||
```javascript
|
||||
config.fatal = true;
|
||||
cp('this_file_does_not_exist', '/dev/null'); // dies here
|
||||
/* more commands... */
|
||||
```
|
||||
|
||||
If `true` the script will die on errors. Default is `false`.
|
||||
51
bin/node_modules/shelljs/bin/shjs
generated
vendored
Executable file
51
bin/node_modules/shelljs/bin/shjs
generated
vendored
Executable file
@@ -0,0 +1,51 @@
|
||||
#!/usr/bin/env node
|
||||
require('../global');
|
||||
|
||||
if (process.argv.length < 3) {
|
||||
console.log('ShellJS: missing argument (script name)');
|
||||
console.log();
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
var args,
|
||||
scriptName = process.argv[2];
|
||||
env['NODE_PATH'] = __dirname + '/../..';
|
||||
|
||||
if (!scriptName.match(/\.js/) && !scriptName.match(/\.coffee/)) {
|
||||
if (test('-f', scriptName + '.js'))
|
||||
scriptName += '.js';
|
||||
if (test('-f', scriptName + '.coffee'))
|
||||
scriptName += '.coffee';
|
||||
}
|
||||
|
||||
if (!test('-f', scriptName)) {
|
||||
console.log('ShellJS: script not found ('+scriptName+')');
|
||||
console.log();
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
args = process.argv.slice(3);
|
||||
|
||||
for (var i = 0, l = args.length; i < l; i++) {
|
||||
if (args[i][0] !== "-"){
|
||||
args[i] = '"' + args[i] + '"'; // fixes arguments with multiple words
|
||||
}
|
||||
}
|
||||
|
||||
if (scriptName.match(/\.coffee$/)) {
|
||||
//
|
||||
// CoffeeScript
|
||||
//
|
||||
if (which('coffee')) {
|
||||
exec('coffee ' + scriptName + ' ' + args.join(' '), { async: true });
|
||||
} else {
|
||||
console.log('ShellJS: CoffeeScript interpreter not found');
|
||||
console.log();
|
||||
process.exit(1);
|
||||
}
|
||||
} else {
|
||||
//
|
||||
// JavaScript
|
||||
//
|
||||
exec('node ' + scriptName + ' ' + args.join(' '), { async: true });
|
||||
}
|
||||
3
bin/node_modules/shelljs/global.js
generated
vendored
Normal file
3
bin/node_modules/shelljs/global.js
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
var shell = require('./shell.js');
|
||||
for (var cmd in shell)
|
||||
global[cmd] = shell[cmd];
|
||||
47
bin/node_modules/shelljs/make.js
generated
vendored
Normal file
47
bin/node_modules/shelljs/make.js
generated
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
require('./global');
|
||||
|
||||
global.config.fatal = true;
|
||||
global.target = {};
|
||||
|
||||
// This ensures we only execute the script targets after the entire script has
|
||||
// been evaluated
|
||||
var args = process.argv.slice(2);
|
||||
setTimeout(function() {
|
||||
var t;
|
||||
|
||||
if (args.length === 1 && args[0] === '--help') {
|
||||
console.log('Available targets:');
|
||||
for (t in global.target)
|
||||
console.log(' ' + t);
|
||||
return;
|
||||
}
|
||||
|
||||
// Wrap targets to prevent duplicate execution
|
||||
for (t in global.target) {
|
||||
(function(t, oldTarget){
|
||||
|
||||
// Wrap it
|
||||
global.target[t] = function(force) {
|
||||
if (oldTarget.done && !force)
|
||||
return;
|
||||
oldTarget.done = true;
|
||||
return oldTarget.apply(oldTarget, arguments);
|
||||
};
|
||||
|
||||
})(t, global.target[t]);
|
||||
}
|
||||
|
||||
// Execute desired targets
|
||||
if (args.length > 0) {
|
||||
args.forEach(function(arg) {
|
||||
if (arg in global.target)
|
||||
global.target[arg]();
|
||||
else {
|
||||
console.log('no such target: ' + arg);
|
||||
}
|
||||
});
|
||||
} else if ('all' in global.target) {
|
||||
global.target.all();
|
||||
}
|
||||
|
||||
}, 0);
|
||||
48
bin/node_modules/shelljs/package.json
generated
vendored
Normal file
48
bin/node_modules/shelljs/package.json
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
21
bin/node_modules/shelljs/scripts/generate-docs.js
generated
vendored
Executable file
21
bin/node_modules/shelljs/scripts/generate-docs.js
generated
vendored
Executable file
@@ -0,0 +1,21 @@
|
||||
#!/usr/bin/env node
|
||||
require('../global');
|
||||
|
||||
echo('Appending docs to README.md');
|
||||
|
||||
cd(__dirname + '/..');
|
||||
|
||||
// Extract docs from shell.js
|
||||
var docs = grep('//@', 'shell.js');
|
||||
|
||||
docs = docs.replace(/\/\/\@include (.+)/g, function(match, path) {
|
||||
var file = path.match('.js$') ? path : path+'.js';
|
||||
return grep('//@', file);
|
||||
});
|
||||
|
||||
// Remove '//@'
|
||||
docs = docs.replace(/\/\/\@ ?/g, '');
|
||||
// Append docs to README
|
||||
sed('-i', /## Command reference(.|\n)*/, '## Command reference\n\n' + docs, 'README.md');
|
||||
|
||||
echo('All done.');
|
||||
50
bin/node_modules/shelljs/scripts/run-tests.js
generated
vendored
Executable file
50
bin/node_modules/shelljs/scripts/run-tests.js
generated
vendored
Executable file
@@ -0,0 +1,50 @@
|
||||
#!/usr/bin/env node
|
||||
require('../global');
|
||||
|
||||
var path = require('path');
|
||||
|
||||
var failed = false;
|
||||
|
||||
//
|
||||
// Lint
|
||||
//
|
||||
JSHINT_BIN = './node_modules/jshint/bin/jshint';
|
||||
cd(__dirname + '/..');
|
||||
|
||||
if (!test('-f', JSHINT_BIN)) {
|
||||
echo('JSHint not found. Run `npm install` in the root dir first.');
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (exec(JSHINT_BIN + ' *.js test/*.js').code !== 0) {
|
||||
failed = true;
|
||||
echo('*** JSHINT FAILED! (return code != 0)');
|
||||
echo();
|
||||
} else {
|
||||
echo('All JSHint tests passed');
|
||||
echo();
|
||||
}
|
||||
|
||||
//
|
||||
// Unit tests
|
||||
//
|
||||
cd(__dirname + '/../test');
|
||||
ls('*.js').forEach(function(file) {
|
||||
echo('Running test:', file);
|
||||
if (exec('node ' + file).code !== 123) { // 123 avoids false positives (e.g. premature exit)
|
||||
failed = true;
|
||||
echo('*** TEST FAILED! (missing exit code "123")');
|
||||
echo();
|
||||
}
|
||||
});
|
||||
|
||||
if (failed) {
|
||||
echo();
|
||||
echo('*******************************************************');
|
||||
echo('WARNING: Some tests did not pass!');
|
||||
echo('*******************************************************');
|
||||
exit(1);
|
||||
} else {
|
||||
echo();
|
||||
echo('All tests passed.');
|
||||
}
|
||||
153
bin/node_modules/shelljs/shell.js
generated
vendored
Normal file
153
bin/node_modules/shelljs/shell.js
generated
vendored
Normal file
@@ -0,0 +1,153 @@
|
||||
//
|
||||
// ShellJS
|
||||
// Unix shell commands on top of Node's API
|
||||
//
|
||||
// Copyright (c) 2012 Artur Adib
|
||||
// http://github.com/arturadib/shelljs
|
||||
//
|
||||
|
||||
var common = require('./src/common');
|
||||
|
||||
|
||||
//@
|
||||
//@ All commands run synchronously, unless otherwise stated.
|
||||
//@
|
||||
|
||||
//@include ./src/cd
|
||||
var _cd = require('./src/cd');
|
||||
exports.cd = common.wrap('cd', _cd);
|
||||
|
||||
//@include ./src/pwd
|
||||
var _pwd = require('./src/pwd');
|
||||
exports.pwd = common.wrap('pwd', _pwd);
|
||||
|
||||
//@include ./src/ls
|
||||
var _ls = require('./src/ls');
|
||||
exports.ls = common.wrap('ls', _ls);
|
||||
|
||||
//@include ./src/find
|
||||
var _find = require('./src/find');
|
||||
exports.find = common.wrap('find', _find);
|
||||
|
||||
//@include ./src/cp
|
||||
var _cp = require('./src/cp');
|
||||
exports.cp = common.wrap('cp', _cp);
|
||||
|
||||
//@include ./src/rm
|
||||
var _rm = require('./src/rm');
|
||||
exports.rm = common.wrap('rm', _rm);
|
||||
|
||||
//@include ./src/mv
|
||||
var _mv = require('./src/mv');
|
||||
exports.mv = common.wrap('mv', _mv);
|
||||
|
||||
//@include ./src/mkdir
|
||||
var _mkdir = require('./src/mkdir');
|
||||
exports.mkdir = common.wrap('mkdir', _mkdir);
|
||||
|
||||
//@include ./src/test
|
||||
var _test = require('./src/test');
|
||||
exports.test = common.wrap('test', _test);
|
||||
|
||||
//@include ./src/cat
|
||||
var _cat = require('./src/cat');
|
||||
exports.cat = common.wrap('cat', _cat);
|
||||
|
||||
//@include ./src/to
|
||||
var _to = require('./src/to');
|
||||
String.prototype.to = common.wrap('to', _to);
|
||||
|
||||
//@include ./src/toEnd
|
||||
var _toEnd = require('./src/toEnd');
|
||||
String.prototype.toEnd = common.wrap('toEnd', _toEnd);
|
||||
|
||||
//@include ./src/sed
|
||||
var _sed = require('./src/sed');
|
||||
exports.sed = common.wrap('sed', _sed);
|
||||
|
||||
//@include ./src/grep
|
||||
var _grep = require('./src/grep');
|
||||
exports.grep = common.wrap('grep', _grep);
|
||||
|
||||
//@include ./src/which
|
||||
var _which = require('./src/which');
|
||||
exports.which = common.wrap('which', _which);
|
||||
|
||||
//@include ./src/echo
|
||||
var _echo = require('./src/echo');
|
||||
exports.echo = _echo; // don't common.wrap() as it could parse '-options'
|
||||
|
||||
//@include ./src/dirs
|
||||
var _dirs = require('./src/dirs').dirs;
|
||||
exports.dirs = common.wrap("dirs", _dirs);
|
||||
var _pushd = require('./src/dirs').pushd;
|
||||
exports.pushd = common.wrap('pushd', _pushd);
|
||||
var _popd = require('./src/dirs').popd;
|
||||
exports.popd = common.wrap("popd", _popd);
|
||||
|
||||
//@
|
||||
//@ ### exit(code)
|
||||
//@ Exits the current process with the given exit code.
|
||||
exports.exit = process.exit;
|
||||
|
||||
//@
|
||||
//@ ### env['VAR_NAME']
|
||||
//@ Object containing environment variables (both getter and setter). Shortcut to process.env.
|
||||
exports.env = process.env;
|
||||
|
||||
//@include ./src/exec
|
||||
var _exec = require('./src/exec');
|
||||
exports.exec = common.wrap('exec', _exec, {notUnix:true});
|
||||
|
||||
//@include ./src/chmod
|
||||
var _chmod = require('./src/chmod');
|
||||
exports.chmod = common.wrap('chmod', _chmod);
|
||||
|
||||
|
||||
|
||||
//@
|
||||
//@ ## Non-Unix commands
|
||||
//@
|
||||
|
||||
//@include ./src/tempdir
|
||||
var _tempDir = require('./src/tempdir');
|
||||
exports.tempdir = common.wrap('tempdir', _tempDir);
|
||||
|
||||
|
||||
//@include ./src/error
|
||||
var _error = require('./src/error');
|
||||
exports.error = _error;
|
||||
|
||||
|
||||
|
||||
//@
|
||||
//@ ## Configuration
|
||||
//@
|
||||
|
||||
exports.config = common.config;
|
||||
|
||||
//@
|
||||
//@ ### config.silent
|
||||
//@ Example:
|
||||
//@
|
||||
//@ ```javascript
|
||||
//@ var silentState = config.silent; // save old silent state
|
||||
//@ config.silent = true;
|
||||
//@ /* ... */
|
||||
//@ config.silent = silentState; // restore old silent state
|
||||
//@ ```
|
||||
//@
|
||||
//@ Suppresses all command output if `true`, except for `echo()` calls.
|
||||
//@ Default is `false`.
|
||||
|
||||
//@
|
||||
//@ ### config.fatal
|
||||
//@ Example:
|
||||
//@
|
||||
//@ ```javascript
|
||||
//@ config.fatal = true;
|
||||
//@ cp('this_file_does_not_exist', '/dev/null'); // dies here
|
||||
//@ /* more commands... */
|
||||
//@ ```
|
||||
//@
|
||||
//@ If `true` the script will die on errors. Default is `false`.
|
||||
43
bin/node_modules/shelljs/src/cat.js
generated
vendored
Normal file
43
bin/node_modules/shelljs/src/cat.js
generated
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
var common = require('./common');
|
||||
var fs = require('fs');
|
||||
|
||||
//@
|
||||
//@ ### cat(file [, file ...])
|
||||
//@ ### cat(file_array)
|
||||
//@
|
||||
//@ Examples:
|
||||
//@
|
||||
//@ ```javascript
|
||||
//@ var str = cat('file*.txt');
|
||||
//@ var str = cat('file1', 'file2');
|
||||
//@ var str = cat(['file1', 'file2']); // same as above
|
||||
//@ ```
|
||||
//@
|
||||
//@ Returns a string containing the given file, or a concatenated string
|
||||
//@ containing the files if more than one file is given (a new line character is
|
||||
//@ introduced between each file). Wildcard `*` accepted.
|
||||
function _cat(options, files) {
|
||||
var cat = '';
|
||||
|
||||
if (!files)
|
||||
common.error('no paths given');
|
||||
|
||||
if (typeof files === 'string')
|
||||
files = [].slice.call(arguments, 1);
|
||||
// if it's array leave it as it is
|
||||
|
||||
files = common.expand(files);
|
||||
|
||||
files.forEach(function(file) {
|
||||
if (!fs.existsSync(file))
|
||||
common.error('no such file or directory: ' + file);
|
||||
|
||||
cat += fs.readFileSync(file, 'utf8') + '\n';
|
||||
});
|
||||
|
||||
if (cat[cat.length-1] === '\n')
|
||||
cat = cat.substring(0, cat.length-1);
|
||||
|
||||
return common.ShellString(cat);
|
||||
}
|
||||
module.exports = _cat;
|
||||
19
bin/node_modules/shelljs/src/cd.js
generated
vendored
Normal file
19
bin/node_modules/shelljs/src/cd.js
generated
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
var fs = require('fs');
|
||||
var common = require('./common');
|
||||
|
||||
//@
|
||||
//@ ### cd('dir')
|
||||
//@ Changes to directory `dir` for the duration of the script
|
||||
function _cd(options, dir) {
|
||||
if (!dir)
|
||||
common.error('directory not specified');
|
||||
|
||||
if (!fs.existsSync(dir))
|
||||
common.error('no such file or directory: ' + dir);
|
||||
|
||||
if (!fs.statSync(dir).isDirectory())
|
||||
common.error('not a directory: ' + dir);
|
||||
|
||||
process.chdir(dir);
|
||||
}
|
||||
module.exports = _cd;
|
||||
208
bin/node_modules/shelljs/src/chmod.js
generated
vendored
Normal file
208
bin/node_modules/shelljs/src/chmod.js
generated
vendored
Normal file
@@ -0,0 +1,208 @@
|
||||
var common = require('./common');
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
|
||||
var PERMS = (function (base) {
|
||||
return {
|
||||
OTHER_EXEC : base.EXEC,
|
||||
OTHER_WRITE : base.WRITE,
|
||||
OTHER_READ : base.READ,
|
||||
|
||||
GROUP_EXEC : base.EXEC << 3,
|
||||
GROUP_WRITE : base.WRITE << 3,
|
||||
GROUP_READ : base.READ << 3,
|
||||
|
||||
OWNER_EXEC : base.EXEC << 6,
|
||||
OWNER_WRITE : base.WRITE << 6,
|
||||
OWNER_READ : base.READ << 6,
|
||||
|
||||
// Literal octal numbers are apparently not allowed in "strict" javascript. Using parseInt is
|
||||
// the preferred way, else a jshint warning is thrown.
|
||||
STICKY : parseInt('01000', 8),
|
||||
SETGID : parseInt('02000', 8),
|
||||
SETUID : parseInt('04000', 8),
|
||||
|
||||
TYPE_MASK : parseInt('0770000', 8)
|
||||
};
|
||||
})({
|
||||
EXEC : 1,
|
||||
WRITE : 2,
|
||||
READ : 4
|
||||
});
|
||||
|
||||
//@
|
||||
//@ ### chmod(octal_mode || octal_string, file)
|
||||
//@ ### chmod(symbolic_mode, file)
|
||||
//@
|
||||
//@ Available options:
|
||||
//@
|
||||
//@ + `-v`: output a diagnostic for every file processed//@
|
||||
//@ + `-c`: like verbose but report only when a change is made//@
|
||||
//@ + `-R`: change files and directories recursively//@
|
||||
//@
|
||||
//@ Examples:
|
||||
//@
|
||||
//@ ```javascript
|
||||
//@ chmod(755, '/Users/brandon');
|
||||
//@ chmod('755', '/Users/brandon'); // same as above
|
||||
//@ chmod('u+x', '/Users/brandon');
|
||||
//@ ```
|
||||
//@
|
||||
//@ Alters the permissions of a file or directory by either specifying the
|
||||
//@ absolute permissions in octal form or expressing the changes in symbols.
|
||||
//@ This command tries to mimic the POSIX behavior as much as possible.
|
||||
//@ Notable exceptions:
|
||||
//@
|
||||
//@ + In symbolic modes, 'a-r' and '-r' are identical. No consideration is
|
||||
//@ given to the umask.
|
||||
//@ + There is no "quiet" option since default behavior is to run silent.
|
||||
function _chmod(options, mode, filePattern) {
|
||||
if (!filePattern) {
|
||||
if (options.length > 0 && options.charAt(0) === '-') {
|
||||
// Special case where the specified file permissions started with - to subtract perms, which
|
||||
// get picked up by the option parser as command flags.
|
||||
// If we are down by one argument and options starts with -, shift everything over.
|
||||
filePattern = mode;
|
||||
mode = options;
|
||||
options = '';
|
||||
}
|
||||
else {
|
||||
common.error('You must specify a file.');
|
||||
}
|
||||
}
|
||||
|
||||
options = common.parseOptions(options, {
|
||||
'R': 'recursive',
|
||||
'c': 'changes',
|
||||
'v': 'verbose'
|
||||
});
|
||||
|
||||
if (typeof filePattern === 'string') {
|
||||
filePattern = [ filePattern ];
|
||||
}
|
||||
|
||||
var files;
|
||||
|
||||
if (options.recursive) {
|
||||
files = [];
|
||||
common.expand(filePattern).forEach(function addFile(expandedFile) {
|
||||
var stat = fs.lstatSync(expandedFile);
|
||||
|
||||
if (!stat.isSymbolicLink()) {
|
||||
files.push(expandedFile);
|
||||
|
||||
if (stat.isDirectory()) { // intentionally does not follow symlinks.
|
||||
fs.readdirSync(expandedFile).forEach(function (child) {
|
||||
addFile(expandedFile + '/' + child);
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
files = common.expand(filePattern);
|
||||
}
|
||||
|
||||
files.forEach(function innerChmod(file) {
|
||||
file = path.resolve(file);
|
||||
if (!fs.existsSync(file)) {
|
||||
common.error('File not found: ' + file);
|
||||
}
|
||||
|
||||
// When recursing, don't follow symlinks.
|
||||
if (options.recursive && fs.lstatSync(file).isSymbolicLink()) {
|
||||
return;
|
||||
}
|
||||
|
||||
var perms = fs.statSync(file).mode;
|
||||
var type = perms & PERMS.TYPE_MASK;
|
||||
|
||||
var newPerms = perms;
|
||||
|
||||
if (isNaN(parseInt(mode, 8))) {
|
||||
// parse options
|
||||
mode.split(',').forEach(function (symbolicMode) {
|
||||
/*jshint regexdash:true */
|
||||
var pattern = /([ugoa]*)([=\+-])([rwxXst]*)/i;
|
||||
var matches = pattern.exec(symbolicMode);
|
||||
|
||||
if (matches) {
|
||||
var applyTo = matches[1];
|
||||
var operator = matches[2];
|
||||
var change = matches[3];
|
||||
|
||||
var changeOwner = applyTo.indexOf('u') != -1 || applyTo === 'a' || applyTo === '';
|
||||
var changeGroup = applyTo.indexOf('g') != -1 || applyTo === 'a' || applyTo === '';
|
||||
var changeOther = applyTo.indexOf('o') != -1 || applyTo === 'a' || applyTo === '';
|
||||
|
||||
var changeRead = change.indexOf('r') != -1;
|
||||
var changeWrite = change.indexOf('w') != -1;
|
||||
var changeExec = change.indexOf('x') != -1;
|
||||
var changeSticky = change.indexOf('t') != -1;
|
||||
var changeSetuid = change.indexOf('s') != -1;
|
||||
|
||||
var mask = 0;
|
||||
if (changeOwner) {
|
||||
mask |= (changeRead ? PERMS.OWNER_READ : 0) + (changeWrite ? PERMS.OWNER_WRITE : 0) + (changeExec ? PERMS.OWNER_EXEC : 0) + (changeSetuid ? PERMS.SETUID : 0);
|
||||
}
|
||||
if (changeGroup) {
|
||||
mask |= (changeRead ? PERMS.GROUP_READ : 0) + (changeWrite ? PERMS.GROUP_WRITE : 0) + (changeExec ? PERMS.GROUP_EXEC : 0) + (changeSetuid ? PERMS.SETGID : 0);
|
||||
}
|
||||
if (changeOther) {
|
||||
mask |= (changeRead ? PERMS.OTHER_READ : 0) + (changeWrite ? PERMS.OTHER_WRITE : 0) + (changeExec ? PERMS.OTHER_EXEC : 0);
|
||||
}
|
||||
|
||||
// Sticky bit is special - it's not tied to user, group or other.
|
||||
if (changeSticky) {
|
||||
mask |= PERMS.STICKY;
|
||||
}
|
||||
|
||||
switch (operator) {
|
||||
case '+':
|
||||
newPerms |= mask;
|
||||
break;
|
||||
|
||||
case '-':
|
||||
newPerms &= ~mask;
|
||||
break;
|
||||
|
||||
case '=':
|
||||
newPerms = type + mask;
|
||||
|
||||
// According to POSIX, when using = to explicitly set the permissions, setuid and setgid can never be cleared.
|
||||
if (fs.statSync(file).isDirectory()) {
|
||||
newPerms |= (PERMS.SETUID + PERMS.SETGID) & perms;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (options.verbose) {
|
||||
log(file + ' -> ' + newPerms.toString(8));
|
||||
}
|
||||
|
||||
if (perms != newPerms) {
|
||||
if (!options.verbose && options.changes) {
|
||||
log(file + ' -> ' + newPerms.toString(8));
|
||||
}
|
||||
fs.chmodSync(file, newPerms);
|
||||
}
|
||||
}
|
||||
else {
|
||||
common.error('Invalid symbolic mode change: ' + symbolicMode);
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
// they gave us a full number
|
||||
newPerms = type + parseInt(mode, 8);
|
||||
|
||||
// POSIX rules are that setuid and setgid can only be added using numeric form, but not cleared.
|
||||
if (fs.statSync(file).isDirectory()) {
|
||||
newPerms |= (PERMS.SETUID + PERMS.SETGID) & perms;
|
||||
}
|
||||
|
||||
fs.chmodSync(file, newPerms);
|
||||
}
|
||||
});
|
||||
}
|
||||
module.exports = _chmod;
|
||||
189
bin/node_modules/shelljs/src/common.js
generated
vendored
Normal file
189
bin/node_modules/shelljs/src/common.js
generated
vendored
Normal file
@@ -0,0 +1,189 @@
|
||||
var os = require('os');
|
||||
var fs = require('fs');
|
||||
var _ls = require('./ls');
|
||||
|
||||
// Module globals
|
||||
var config = {
|
||||
silent: false,
|
||||
fatal: false
|
||||
};
|
||||
exports.config = config;
|
||||
|
||||
var state = {
|
||||
error: null,
|
||||
currentCmd: 'shell.js',
|
||||
tempDir: null
|
||||
};
|
||||
exports.state = state;
|
||||
|
||||
var platform = os.type().match(/^Win/) ? 'win' : 'unix';
|
||||
exports.platform = platform;
|
||||
|
||||
function log() {
|
||||
if (!config.silent)
|
||||
console.log.apply(this, arguments);
|
||||
}
|
||||
exports.log = log;
|
||||
|
||||
// Shows error message. Throws unless _continue or config.fatal are true
|
||||
function error(msg, _continue) {
|
||||
if (state.error === null)
|
||||
state.error = '';
|
||||
state.error += state.currentCmd + ': ' + msg + '\n';
|
||||
|
||||
if (msg.length > 0)
|
||||
log(state.error);
|
||||
|
||||
if (config.fatal)
|
||||
process.exit(1);
|
||||
|
||||
if (!_continue)
|
||||
throw '';
|
||||
}
|
||||
exports.error = error;
|
||||
|
||||
// In the future, when Proxies are default, we can add methods like `.to()` to primitive strings.
|
||||
// For now, this is a dummy function to bookmark places we need such strings
|
||||
function ShellString(str) {
|
||||
return str;
|
||||
}
|
||||
exports.ShellString = ShellString;
|
||||
|
||||
// Returns {'alice': true, 'bob': false} when passed a dictionary, e.g.:
|
||||
// parseOptions('-a', {'a':'alice', 'b':'bob'});
|
||||
function parseOptions(str, map) {
|
||||
if (!map)
|
||||
error('parseOptions() internal error: no map given');
|
||||
|
||||
// All options are false by default
|
||||
var options = {};
|
||||
for (var letter in map)
|
||||
options[map[letter]] = false;
|
||||
|
||||
if (!str)
|
||||
return options; // defaults
|
||||
|
||||
if (typeof str !== 'string')
|
||||
error('parseOptions() internal error: wrong str');
|
||||
|
||||
// e.g. match[1] = 'Rf' for str = '-Rf'
|
||||
var match = str.match(/^\-(.+)/);
|
||||
if (!match)
|
||||
return options;
|
||||
|
||||
// e.g. chars = ['R', 'f']
|
||||
var chars = match[1].split('');
|
||||
|
||||
chars.forEach(function(c) {
|
||||
if (c in map)
|
||||
options[map[c]] = true;
|
||||
else
|
||||
error('option not recognized: '+c);
|
||||
});
|
||||
|
||||
return options;
|
||||
}
|
||||
exports.parseOptions = parseOptions;
|
||||
|
||||
// Expands wildcards with matching (ie. existing) file names.
|
||||
// For example:
|
||||
// expand(['file*.js']) = ['file1.js', 'file2.js', ...]
|
||||
// (if the files 'file1.js', 'file2.js', etc, exist in the current dir)
|
||||
function expand(list) {
|
||||
var expanded = [];
|
||||
list.forEach(function(listEl) {
|
||||
// Wildcard present?
|
||||
if (listEl.search(/\*/) > -1) {
|
||||
_ls('', listEl).forEach(function(file) {
|
||||
expanded.push(file);
|
||||
});
|
||||
} else {
|
||||
expanded.push(listEl);
|
||||
}
|
||||
});
|
||||
return expanded;
|
||||
}
|
||||
exports.expand = expand;
|
||||
|
||||
// Normalizes _unlinkSync() across platforms to match Unix behavior, i.e.
|
||||
// file can be unlinked even if it's read-only, see https://github.com/joyent/node/issues/3006
|
||||
function unlinkSync(file) {
|
||||
try {
|
||||
fs.unlinkSync(file);
|
||||
} catch(e) {
|
||||
// Try to override file permission
|
||||
if (e.code === 'EPERM') {
|
||||
fs.chmodSync(file, '0666');
|
||||
fs.unlinkSync(file);
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
exports.unlinkSync = unlinkSync;
|
||||
|
||||
// e.g. 'shelljs_a5f185d0443ca...'
|
||||
function randomFileName() {
|
||||
function randomHash(count) {
|
||||
if (count === 1)
|
||||
return parseInt(16*Math.random(), 10).toString(16);
|
||||
else {
|
||||
var hash = '';
|
||||
for (var i=0; i<count; i++)
|
||||
hash += randomHash(1);
|
||||
return hash;
|
||||
}
|
||||
}
|
||||
|
||||
return 'shelljs_'+randomHash(20);
|
||||
}
|
||||
exports.randomFileName = randomFileName;
|
||||
|
||||
// extend(target_obj, source_obj1 [, source_obj2 ...])
|
||||
// Shallow extend, e.g.:
|
||||
// extend({A:1}, {b:2}, {c:3}) returns {A:1, b:2, c:3}
|
||||
function extend(target) {
|
||||
var sources = [].slice.call(arguments, 1);
|
||||
sources.forEach(function(source) {
|
||||
for (var key in source)
|
||||
target[key] = source[key];
|
||||
});
|
||||
|
||||
return target;
|
||||
}
|
||||
exports.extend = extend;
|
||||
|
||||
// Common wrapper for all Unix-like commands
|
||||
function wrap(cmd, fn, options) {
|
||||
return function() {
|
||||
var retValue = null;
|
||||
|
||||
state.currentCmd = cmd;
|
||||
state.error = null;
|
||||
|
||||
try {
|
||||
var args = [].slice.call(arguments, 0);
|
||||
|
||||
if (options && options.notUnix) {
|
||||
retValue = fn.apply(this, args);
|
||||
} else {
|
||||
if (args.length === 0 || typeof args[0] !== 'string' || args[0][0] !== '-')
|
||||
args.unshift(''); // only add dummy option if '-option' not already present
|
||||
retValue = fn.apply(this, args);
|
||||
}
|
||||
} catch (e) {
|
||||
if (!state.error) {
|
||||
// If state.error hasn't been set it's an error thrown by Node, not us - probably a bug...
|
||||
console.log('shell.js: internal error');
|
||||
console.log(e.stack || e);
|
||||
process.exit(1);
|
||||
}
|
||||
if (config.fatal)
|
||||
throw e;
|
||||
}
|
||||
|
||||
state.currentCmd = 'shell.js';
|
||||
return retValue;
|
||||
};
|
||||
} // wrap
|
||||
exports.wrap = wrap;
|
||||
200
bin/node_modules/shelljs/src/cp.js
generated
vendored
Normal file
200
bin/node_modules/shelljs/src/cp.js
generated
vendored
Normal file
@@ -0,0 +1,200 @@
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
var common = require('./common');
|
||||
|
||||
// Buffered file copy, synchronous
|
||||
// (Using readFileSync() + writeFileSync() could easily cause a memory overflow
|
||||
// with large files)
|
||||
function copyFileSync(srcFile, destFile) {
|
||||
if (!fs.existsSync(srcFile))
|
||||
common.error('copyFileSync: no such file or directory: ' + srcFile);
|
||||
|
||||
var BUF_LENGTH = 64*1024,
|
||||
buf = new Buffer(BUF_LENGTH),
|
||||
bytesRead = BUF_LENGTH,
|
||||
pos = 0,
|
||||
fdr = null,
|
||||
fdw = null;
|
||||
|
||||
try {
|
||||
fdr = fs.openSync(srcFile, 'r');
|
||||
} catch(e) {
|
||||
common.error('copyFileSync: could not read src file ('+srcFile+')');
|
||||
}
|
||||
|
||||
try {
|
||||
fdw = fs.openSync(destFile, 'w');
|
||||
} catch(e) {
|
||||
common.error('copyFileSync: could not write to dest file (code='+e.code+'):'+destFile);
|
||||
}
|
||||
|
||||
while (bytesRead === BUF_LENGTH) {
|
||||
bytesRead = fs.readSync(fdr, buf, 0, BUF_LENGTH, pos);
|
||||
fs.writeSync(fdw, buf, 0, bytesRead);
|
||||
pos += bytesRead;
|
||||
}
|
||||
|
||||
fs.closeSync(fdr);
|
||||
fs.closeSync(fdw);
|
||||
|
||||
fs.chmodSync(destFile, fs.statSync(srcFile).mode);
|
||||
}
|
||||
|
||||
// Recursively copies 'sourceDir' into 'destDir'
|
||||
// Adapted from https://github.com/ryanmcgrath/wrench-js
|
||||
//
|
||||
// Copyright (c) 2010 Ryan McGrath
|
||||
// Copyright (c) 2012 Artur Adib
|
||||
//
|
||||
// Licensed under the MIT License
|
||||
// http://www.opensource.org/licenses/mit-license.php
|
||||
function cpdirSyncRecursive(sourceDir, destDir, opts) {
|
||||
if (!opts) opts = {};
|
||||
|
||||
/* Create the directory where all our junk is moving to; read the mode of the source directory and mirror it */
|
||||
var checkDir = fs.statSync(sourceDir);
|
||||
try {
|
||||
fs.mkdirSync(destDir, checkDir.mode);
|
||||
} catch (e) {
|
||||
//if the directory already exists, that's okay
|
||||
if (e.code !== 'EEXIST') throw e;
|
||||
}
|
||||
|
||||
var files = fs.readdirSync(sourceDir);
|
||||
|
||||
for (var i = 0; i < files.length; i++) {
|
||||
var srcFile = sourceDir + "/" + files[i];
|
||||
var destFile = destDir + "/" + files[i];
|
||||
var srcFileStat = fs.lstatSync(srcFile);
|
||||
|
||||
if (srcFileStat.isDirectory()) {
|
||||
/* recursion this thing right on back. */
|
||||
cpdirSyncRecursive(srcFile, destFile, opts);
|
||||
} else if (srcFileStat.isSymbolicLink()) {
|
||||
var symlinkFull = fs.readlinkSync(srcFile);
|
||||
fs.symlinkSync(symlinkFull, destFile);
|
||||
} else {
|
||||
/* At this point, we've hit a file actually worth copying... so copy it on over. */
|
||||
if (fs.existsSync(destFile) && !opts.force) {
|
||||
common.log('skipping existing file: ' + files[i]);
|
||||
} else {
|
||||
copyFileSync(srcFile, destFile);
|
||||
}
|
||||
}
|
||||
|
||||
} // for files
|
||||
} // cpdirSyncRecursive
|
||||
|
||||
|
||||
//@
|
||||
//@ ### cp([options ,] source [,source ...], dest)
|
||||
//@ ### cp([options ,] source_array, dest)
|
||||
//@ Available options:
|
||||
//@
|
||||
//@ + `-f`: force
|
||||
//@ + `-r, -R`: recursive
|
||||
//@
|
||||
//@ Examples:
|
||||
//@
|
||||
//@ ```javascript
|
||||
//@ cp('file1', 'dir1');
|
||||
//@ cp('-Rf', '/tmp/*', '/usr/local/*', '/home/tmp');
|
||||
//@ cp('-Rf', ['/tmp/*', '/usr/local/*'], '/home/tmp'); // same as above
|
||||
//@ ```
|
||||
//@
|
||||
//@ Copies files. The wildcard `*` is accepted.
|
||||
function _cp(options, sources, dest) {
|
||||
options = common.parseOptions(options, {
|
||||
'f': 'force',
|
||||
'R': 'recursive',
|
||||
'r': 'recursive'
|
||||
});
|
||||
|
||||
// Get sources, dest
|
||||
if (arguments.length < 3) {
|
||||
common.error('missing <source> and/or <dest>');
|
||||
} else if (arguments.length > 3) {
|
||||
sources = [].slice.call(arguments, 1, arguments.length - 1);
|
||||
dest = arguments[arguments.length - 1];
|
||||
} else if (typeof sources === 'string') {
|
||||
sources = [sources];
|
||||
} else if ('length' in sources) {
|
||||
sources = sources; // no-op for array
|
||||
} else {
|
||||
common.error('invalid arguments');
|
||||
}
|
||||
|
||||
var exists = fs.existsSync(dest),
|
||||
stats = exists && fs.statSync(dest);
|
||||
|
||||
// Dest is not existing dir, but multiple sources given
|
||||
if ((!exists || !stats.isDirectory()) && sources.length > 1)
|
||||
common.error('dest is not a directory (too many sources)');
|
||||
|
||||
// Dest is an existing file, but no -f given
|
||||
if (exists && stats.isFile() && !options.force)
|
||||
common.error('dest file already exists: ' + dest);
|
||||
|
||||
if (options.recursive) {
|
||||
// Recursive allows the shortcut syntax "sourcedir/" for "sourcedir/*"
|
||||
// (see Github issue #15)
|
||||
sources.forEach(function(src, i) {
|
||||
if (src[src.length - 1] === '/')
|
||||
sources[i] += '*';
|
||||
});
|
||||
|
||||
// Create dest
|
||||
try {
|
||||
fs.mkdirSync(dest, parseInt('0777', 8));
|
||||
} catch (e) {
|
||||
// like Unix's cp, keep going even if we can't create dest dir
|
||||
}
|
||||
}
|
||||
|
||||
sources = common.expand(sources);
|
||||
|
||||
sources.forEach(function(src) {
|
||||
if (!fs.existsSync(src)) {
|
||||
common.error('no such file or directory: '+src, true);
|
||||
return; // skip file
|
||||
}
|
||||
|
||||
// If here, src exists
|
||||
if (fs.statSync(src).isDirectory()) {
|
||||
if (!options.recursive) {
|
||||
// Non-Recursive
|
||||
common.log(src + ' is a directory (not copied)');
|
||||
} else {
|
||||
// Recursive
|
||||
// 'cp /a/source dest' should create 'source' in 'dest'
|
||||
var newDest = path.join(dest, path.basename(src)),
|
||||
checkDir = fs.statSync(src);
|
||||
try {
|
||||
fs.mkdirSync(newDest, checkDir.mode);
|
||||
} catch (e) {
|
||||
//if the directory already exists, that's okay
|
||||
if (e.code !== 'EEXIST') throw e;
|
||||
}
|
||||
|
||||
cpdirSyncRecursive(src, newDest, {force: options.force});
|
||||
}
|
||||
return; // done with dir
|
||||
}
|
||||
|
||||
// If here, src is a file
|
||||
|
||||
// When copying to '/path/dir':
|
||||
// thisDest = '/path/dir/file1'
|
||||
var thisDest = dest;
|
||||
if (fs.existsSync(dest) && fs.statSync(dest).isDirectory())
|
||||
thisDest = path.normalize(dest + '/' + path.basename(src));
|
||||
|
||||
if (fs.existsSync(thisDest) && !options.force) {
|
||||
common.error('dest file already exists: ' + thisDest, true);
|
||||
return; // skip file
|
||||
}
|
||||
|
||||
copyFileSync(src, thisDest);
|
||||
}); // forEach(src)
|
||||
}
|
||||
module.exports = _cp;
|
||||
191
bin/node_modules/shelljs/src/dirs.js
generated
vendored
Normal file
191
bin/node_modules/shelljs/src/dirs.js
generated
vendored
Normal file
@@ -0,0 +1,191 @@
|
||||
var common = require('./common');
|
||||
var _cd = require('./cd');
|
||||
var path = require('path');
|
||||
|
||||
// Pushd/popd/dirs internals
|
||||
var _dirStack = [];
|
||||
|
||||
function _isStackIndex(index) {
|
||||
return (/^[\-+]\d+$/).test(index);
|
||||
}
|
||||
|
||||
function _parseStackIndex(index) {
|
||||
if (_isStackIndex(index)) {
|
||||
if (Math.abs(index) < _dirStack.length + 1) { // +1 for pwd
|
||||
return (/^-/).test(index) ? Number(index) - 1 : Number(index);
|
||||
} else {
|
||||
common.error(index + ': directory stack index out of range');
|
||||
}
|
||||
} else {
|
||||
common.error(index + ': invalid number');
|
||||
}
|
||||
}
|
||||
|
||||
function _actualDirStack() {
|
||||
return [process.cwd()].concat(_dirStack);
|
||||
}
|
||||
|
||||
//@
|
||||
//@ ### pushd([options,] [dir | '-N' | '+N'])
|
||||
//@
|
||||
//@ Available options:
|
||||
//@
|
||||
//@ + `-n`: Suppresses the normal change of directory when adding directories to the stack, so that only the stack is manipulated.
|
||||
//@
|
||||
//@ Arguments:
|
||||
//@
|
||||
//@ + `dir`: Makes the current working directory be the top of the stack, and then executes the equivalent of `cd dir`.
|
||||
//@ + `+N`: Brings the Nth directory (counting from the left of the list printed by dirs, starting with zero) to the top of the list by rotating the stack.
|
||||
//@ + `-N`: Brings the Nth directory (counting from the right of the list printed by dirs, starting with zero) to the top of the list by rotating the stack.
|
||||
//@
|
||||
//@ Examples:
|
||||
//@
|
||||
//@ ```javascript
|
||||
//@ // process.cwd() === '/usr'
|
||||
//@ pushd('/etc'); // Returns /etc /usr
|
||||
//@ pushd('+1'); // Returns /usr /etc
|
||||
//@ ```
|
||||
//@
|
||||
//@ Save the current directory on the top of the directory stack and then cd to `dir`. With no arguments, pushd exchanges the top two directories. Returns an array of paths in the stack.
|
||||
function _pushd(options, dir) {
|
||||
if (_isStackIndex(options)) {
|
||||
dir = options;
|
||||
options = '';
|
||||
}
|
||||
|
||||
options = common.parseOptions(options, {
|
||||
'n' : 'no-cd'
|
||||
});
|
||||
|
||||
var dirs = _actualDirStack();
|
||||
|
||||
if (dir === '+0') {
|
||||
return dirs; // +0 is a noop
|
||||
} else if (!dir) {
|
||||
if (dirs.length > 1) {
|
||||
dirs = dirs.splice(1, 1).concat(dirs);
|
||||
} else {
|
||||
return common.error('no other directory');
|
||||
}
|
||||
} else if (_isStackIndex(dir)) {
|
||||
var n = _parseStackIndex(dir);
|
||||
dirs = dirs.slice(n).concat(dirs.slice(0, n));
|
||||
} else {
|
||||
if (options['no-cd']) {
|
||||
dirs.splice(1, 0, dir);
|
||||
} else {
|
||||
dirs.unshift(dir);
|
||||
}
|
||||
}
|
||||
|
||||
if (options['no-cd']) {
|
||||
dirs = dirs.slice(1);
|
||||
} else {
|
||||
dir = path.resolve(dirs.shift());
|
||||
_cd('', dir);
|
||||
}
|
||||
|
||||
_dirStack = dirs;
|
||||
return _dirs('');
|
||||
}
|
||||
exports.pushd = _pushd;
|
||||
|
||||
//@
|
||||
//@ ### popd([options,] ['-N' | '+N'])
|
||||
//@
|
||||
//@ Available options:
|
||||
//@
|
||||
//@ + `-n`: Suppresses the normal change of directory when removing directories from the stack, so that only the stack is manipulated.
|
||||
//@
|
||||
//@ Arguments:
|
||||
//@
|
||||
//@ + `+N`: Removes the Nth directory (counting from the left of the list printed by dirs), starting with zero.
|
||||
//@ + `-N`: Removes the Nth directory (counting from the right of the list printed by dirs), starting with zero.
|
||||
//@
|
||||
//@ Examples:
|
||||
//@
|
||||
//@ ```javascript
|
||||
//@ echo(process.cwd()); // '/usr'
|
||||
//@ pushd('/etc'); // '/etc /usr'
|
||||
//@ echo(process.cwd()); // '/etc'
|
||||
//@ popd(); // '/usr'
|
||||
//@ echo(process.cwd()); // '/usr'
|
||||
//@ ```
|
||||
//@
|
||||
//@ When no arguments are given, popd removes the top directory from the stack and performs a cd to the new top directory. The elements are numbered from 0 starting at the first directory listed with dirs; i.e., popd is equivalent to popd +0. Returns an array of paths in the stack.
|
||||
function _popd(options, index) {
|
||||
if (_isStackIndex(options)) {
|
||||
index = options;
|
||||
options = '';
|
||||
}
|
||||
|
||||
options = common.parseOptions(options, {
|
||||
'n' : 'no-cd'
|
||||
});
|
||||
|
||||
if (!_dirStack.length) {
|
||||
return common.error('directory stack empty');
|
||||
}
|
||||
|
||||
index = _parseStackIndex(index || '+0');
|
||||
|
||||
if (options['no-cd'] || index > 0 || _dirStack.length + index === 0) {
|
||||
index = index > 0 ? index - 1 : index;
|
||||
_dirStack.splice(index, 1);
|
||||
} else {
|
||||
var dir = path.resolve(_dirStack.shift());
|
||||
_cd('', dir);
|
||||
}
|
||||
|
||||
return _dirs('');
|
||||
}
|
||||
exports.popd = _popd;
|
||||
|
||||
//@
|
||||
//@ ### dirs([options | '+N' | '-N'])
|
||||
//@
|
||||
//@ Available options:
|
||||
//@
|
||||
//@ + `-c`: Clears the directory stack by deleting all of the elements.
|
||||
//@
|
||||
//@ Arguments:
|
||||
//@
|
||||
//@ + `+N`: Displays the Nth directory (counting from the left of the list printed by dirs when invoked without options), starting with zero.
|
||||
//@ + `-N`: Displays the Nth directory (counting from the right of the list printed by dirs when invoked without options), starting with zero.
|
||||
//@
|
||||
//@ Display the list of currently remembered directories. Returns an array of paths in the stack, or a single path if +N or -N was specified.
|
||||
//@
|
||||
//@ See also: pushd, popd
|
||||
function _dirs(options, index) {
|
||||
if (_isStackIndex(options)) {
|
||||
index = options;
|
||||
options = '';
|
||||
}
|
||||
|
||||
options = common.parseOptions(options, {
|
||||
'c' : 'clear'
|
||||
});
|
||||
|
||||
if (options['clear']) {
|
||||
_dirStack = [];
|
||||
return _dirStack;
|
||||
}
|
||||
|
||||
var stack = _actualDirStack();
|
||||
|
||||
if (index) {
|
||||
index = _parseStackIndex(index);
|
||||
|
||||
if (index < 0) {
|
||||
index = stack.length + index;
|
||||
}
|
||||
|
||||
common.log(stack[index]);
|
||||
return stack[index];
|
||||
}
|
||||
|
||||
common.log(stack.join(' '));
|
||||
|
||||
return stack;
|
||||
}
|
||||
exports.dirs = _dirs;
|
||||
20
bin/node_modules/shelljs/src/echo.js
generated
vendored
Normal file
20
bin/node_modules/shelljs/src/echo.js
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
var common = require('./common');
|
||||
|
||||
//@
|
||||
//@ ### echo(string [,string ...])
|
||||
//@
|
||||
//@ Examples:
|
||||
//@
|
||||
//@ ```javascript
|
||||
//@ echo('hello world');
|
||||
//@ var str = echo('hello world');
|
||||
//@ ```
|
||||
//@
|
||||
//@ Prints string to stdout, and returns string with additional utility methods
|
||||
//@ like `.to()`.
|
||||
function _echo() {
|
||||
var messages = [].slice.call(arguments, 0);
|
||||
console.log.apply(this, messages);
|
||||
return common.ShellString(messages.join(' '));
|
||||
}
|
||||
module.exports = _echo;
|
||||
10
bin/node_modules/shelljs/src/error.js
generated
vendored
Normal file
10
bin/node_modules/shelljs/src/error.js
generated
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
var common = require('./common');
|
||||
|
||||
//@
|
||||
//@ ### error()
|
||||
//@ Tests if error occurred in the last command. Returns `null` if no error occurred,
|
||||
//@ otherwise returns string explaining the error
|
||||
function error() {
|
||||
return common.state.error;
|
||||
};
|
||||
module.exports = error;
|
||||
181
bin/node_modules/shelljs/src/exec.js
generated
vendored
Normal file
181
bin/node_modules/shelljs/src/exec.js
generated
vendored
Normal file
@@ -0,0 +1,181 @@
|
||||
var common = require('./common');
|
||||
var _tempDir = require('./tempdir');
|
||||
var _pwd = require('./pwd');
|
||||
var path = require('path');
|
||||
var fs = require('fs');
|
||||
var child = require('child_process');
|
||||
|
||||
// Hack to run child_process.exec() synchronously (sync avoids callback hell)
|
||||
// Uses a custom wait loop that checks for a flag file, created when the child process is done.
|
||||
// (Can't do a wait loop that checks for internal Node variables/messages as
|
||||
// Node is single-threaded; callbacks and other internal state changes are done in the
|
||||
// event loop).
|
||||
function execSync(cmd, opts) {
|
||||
var tempDir = _tempDir();
|
||||
var stdoutFile = path.resolve(tempDir+'/'+common.randomFileName()),
|
||||
codeFile = path.resolve(tempDir+'/'+common.randomFileName()),
|
||||
scriptFile = path.resolve(tempDir+'/'+common.randomFileName()),
|
||||
sleepFile = path.resolve(tempDir+'/'+common.randomFileName());
|
||||
|
||||
var options = common.extend({
|
||||
silent: common.config.silent
|
||||
}, opts);
|
||||
|
||||
var previousStdoutContent = '';
|
||||
// Echoes stdout changes from running process, if not silent
|
||||
function updateStdout() {
|
||||
if (options.silent || !fs.existsSync(stdoutFile))
|
||||
return;
|
||||
|
||||
var stdoutContent = fs.readFileSync(stdoutFile, 'utf8');
|
||||
// No changes since last time?
|
||||
if (stdoutContent.length <= previousStdoutContent.length)
|
||||
return;
|
||||
|
||||
process.stdout.write(stdoutContent.substr(previousStdoutContent.length));
|
||||
previousStdoutContent = stdoutContent;
|
||||
}
|
||||
|
||||
function escape(str) {
|
||||
return (str+'').replace(/([\\"'])/g, "\\$1").replace(/\0/g, "\\0");
|
||||
}
|
||||
|
||||
cmd += ' > '+stdoutFile+' 2>&1'; // works on both win/unix
|
||||
|
||||
var script =
|
||||
"var child = require('child_process')," +
|
||||
" fs = require('fs');" +
|
||||
"child.exec('"+escape(cmd)+"', {env: process.env, maxBuffer: 20*1024*1024}, function(err) {" +
|
||||
" fs.writeFileSync('"+escape(codeFile)+"', err ? err.code.toString() : '0');" +
|
||||
"});";
|
||||
|
||||
if (fs.existsSync(scriptFile)) common.unlinkSync(scriptFile);
|
||||
if (fs.existsSync(stdoutFile)) common.unlinkSync(stdoutFile);
|
||||
if (fs.existsSync(codeFile)) common.unlinkSync(codeFile);
|
||||
|
||||
fs.writeFileSync(scriptFile, script);
|
||||
child.exec('"'+process.execPath+'" '+scriptFile, {
|
||||
env: process.env,
|
||||
cwd: _pwd(),
|
||||
maxBuffer: 20*1024*1024
|
||||
});
|
||||
|
||||
// The wait loop
|
||||
// sleepFile is used as a dummy I/O op to mitigate unnecessary CPU usage
|
||||
// (tried many I/O sync ops, writeFileSync() seems to be only one that is effective in reducing
|
||||
// CPU usage, though apparently not so much on Windows)
|
||||
while (!fs.existsSync(codeFile)) { updateStdout(); fs.writeFileSync(sleepFile, 'a'); }
|
||||
while (!fs.existsSync(stdoutFile)) { updateStdout(); fs.writeFileSync(sleepFile, 'a'); }
|
||||
|
||||
// At this point codeFile exists, but it's not necessarily flushed yet.
|
||||
// Keep reading it until it is.
|
||||
var code = parseInt('', 10);
|
||||
while (isNaN(code)) {
|
||||
code = parseInt(fs.readFileSync(codeFile, 'utf8'), 10);
|
||||
}
|
||||
|
||||
var stdout = fs.readFileSync(stdoutFile, 'utf8');
|
||||
|
||||
// No biggie if we can't erase the files now -- they're in a temp dir anyway
|
||||
try { common.unlinkSync(scriptFile); } catch(e) {}
|
||||
try { common.unlinkSync(stdoutFile); } catch(e) {}
|
||||
try { common.unlinkSync(codeFile); } catch(e) {}
|
||||
try { common.unlinkSync(sleepFile); } catch(e) {}
|
||||
|
||||
// some shell return codes are defined as errors, per http://tldp.org/LDP/abs/html/exitcodes.html
|
||||
if (code === 1 || code === 2 || code >= 126) {
|
||||
common.error('', true); // unix/shell doesn't really give an error message after non-zero exit codes
|
||||
}
|
||||
// True if successful, false if not
|
||||
var obj = {
|
||||
code: code,
|
||||
output: stdout
|
||||
};
|
||||
return obj;
|
||||
} // execSync()
|
||||
|
||||
// Wrapper around exec() to enable echoing output to console in real time
|
||||
function execAsync(cmd, opts, callback) {
|
||||
var output = '';
|
||||
|
||||
var options = common.extend({
|
||||
silent: common.config.silent
|
||||
}, opts);
|
||||
|
||||
var c = child.exec(cmd, {env: process.env, maxBuffer: 20*1024*1024}, function(err) {
|
||||
if (callback)
|
||||
callback(err ? err.code : 0, output);
|
||||
});
|
||||
|
||||
c.stdout.on('data', function(data) {
|
||||
output += data;
|
||||
if (!options.silent)
|
||||
process.stdout.write(data);
|
||||
});
|
||||
|
||||
c.stderr.on('data', function(data) {
|
||||
output += data;
|
||||
if (!options.silent)
|
||||
process.stdout.write(data);
|
||||
});
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
//@
|
||||
//@ ### exec(command [, options] [, callback])
|
||||
//@ Available options (all `false` by default):
|
||||
//@
|
||||
//@ + `async`: Asynchronous execution. Defaults to true if a callback is provided.
|
||||
//@ + `silent`: Do not echo program output to console.
|
||||
//@
|
||||
//@ Examples:
|
||||
//@
|
||||
//@ ```javascript
|
||||
//@ var version = exec('node --version', {silent:true}).output;
|
||||
//@
|
||||
//@ var child = exec('some_long_running_process', {async:true});
|
||||
//@ child.stdout.on('data', function(data) {
|
||||
//@ /* ... do something with data ... */
|
||||
//@ });
|
||||
//@
|
||||
//@ exec('some_long_running_process', function(code, output) {
|
||||
//@ console.log('Exit code:', code);
|
||||
//@ console.log('Program output:', output);
|
||||
//@ });
|
||||
//@ ```
|
||||
//@
|
||||
//@ Executes the given `command` _synchronously_, unless otherwise specified.
|
||||
//@ When in synchronous mode returns the object `{ code:..., output:... }`, containing the program's
|
||||
//@ `output` (stdout + stderr) and its exit `code`. Otherwise returns the child process object, and
|
||||
//@ the `callback` gets the arguments `(code, output)`.
|
||||
//@
|
||||
//@ **Note:** For long-lived processes, it's best to run `exec()` asynchronously as
|
||||
//@ the current synchronous implementation uses a lot of CPU. This should be getting
|
||||
//@ fixed soon.
|
||||
function _exec(command, options, callback) {
|
||||
if (!command)
|
||||
common.error('must specify command');
|
||||
|
||||
// Callback is defined instead of options.
|
||||
if (typeof options === 'function') {
|
||||
callback = options;
|
||||
options = { async: true };
|
||||
}
|
||||
|
||||
// Callback is defined with options.
|
||||
if (typeof options === 'object' && typeof callback === 'function') {
|
||||
options.async = true;
|
||||
}
|
||||
|
||||
options = common.extend({
|
||||
silent: common.config.silent,
|
||||
async: false
|
||||
}, options);
|
||||
|
||||
if (options.async)
|
||||
return execAsync(command, options, callback);
|
||||
else
|
||||
return execSync(command, options);
|
||||
}
|
||||
module.exports = _exec;
|
||||
51
bin/node_modules/shelljs/src/find.js
generated
vendored
Normal file
51
bin/node_modules/shelljs/src/find.js
generated
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
var fs = require('fs');
|
||||
var common = require('./common');
|
||||
var _ls = require('./ls');
|
||||
|
||||
//@
|
||||
//@ ### find(path [,path ...])
|
||||
//@ ### find(path_array)
|
||||
//@ Examples:
|
||||
//@
|
||||
//@ ```javascript
|
||||
//@ find('src', 'lib');
|
||||
//@ find(['src', 'lib']); // same as above
|
||||
//@ find('.').filter(function(file) { return file.match(/\.js$/); });
|
||||
//@ ```
|
||||
//@
|
||||
//@ Returns array of all files (however deep) in the given paths.
|
||||
//@
|
||||
//@ The main difference from `ls('-R', path)` is that the resulting file names
|
||||
//@ include the base directories, e.g. `lib/resources/file1` instead of just `file1`.
|
||||
function _find(options, paths) {
|
||||
if (!paths)
|
||||
common.error('no path specified');
|
||||
else if (typeof paths === 'object')
|
||||
paths = paths; // assume array
|
||||
else if (typeof paths === 'string')
|
||||
paths = [].slice.call(arguments, 1);
|
||||
|
||||
var list = [];
|
||||
|
||||
function pushFile(file) {
|
||||
if (common.platform === 'win')
|
||||
file = file.replace(/\\/g, '/');
|
||||
list.push(file);
|
||||
}
|
||||
|
||||
// why not simply do ls('-R', paths)? because the output wouldn't give the base dirs
|
||||
// to get the base dir in the output, we need instead ls('-R', 'dir/*') for every directory
|
||||
|
||||
paths.forEach(function(file) {
|
||||
pushFile(file);
|
||||
|
||||
if (fs.statSync(file).isDirectory()) {
|
||||
_ls('-RA', file+'/*').forEach(function(subfile) {
|
||||
pushFile(subfile);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return list;
|
||||
}
|
||||
module.exports = _find;
|
||||
52
bin/node_modules/shelljs/src/grep.js
generated
vendored
Normal file
52
bin/node_modules/shelljs/src/grep.js
generated
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
var common = require('./common');
|
||||
var fs = require('fs');
|
||||
|
||||
//@
|
||||
//@ ### grep([options ,] regex_filter, file [, file ...])
|
||||
//@ ### grep([options ,] regex_filter, file_array)
|
||||
//@ Available options:
|
||||
//@
|
||||
//@ + `-v`: Inverse the sense of the regex and print the lines not matching the criteria.
|
||||
//@
|
||||
//@ Examples:
|
||||
//@
|
||||
//@ ```javascript
|
||||
//@ grep('-v', 'GLOBAL_VARIABLE', '*.js');
|
||||
//@ grep('GLOBAL_VARIABLE', '*.js');
|
||||
//@ ```
|
||||
//@
|
||||
//@ Reads input string from given files and returns a string containing all lines of the
|
||||
//@ file that match the given `regex_filter`. Wildcard `*` accepted.
|
||||
function _grep(options, regex, files) {
|
||||
options = common.parseOptions(options, {
|
||||
'v': 'inverse'
|
||||
});
|
||||
|
||||
if (!files)
|
||||
common.error('no paths given');
|
||||
|
||||
if (typeof files === 'string')
|
||||
files = [].slice.call(arguments, 2);
|
||||
// if it's array leave it as it is
|
||||
|
||||
files = common.expand(files);
|
||||
|
||||
var grep = '';
|
||||
files.forEach(function(file) {
|
||||
if (!fs.existsSync(file)) {
|
||||
common.error('no such file or directory: ' + file, true);
|
||||
return;
|
||||
}
|
||||
|
||||
var contents = fs.readFileSync(file, 'utf8'),
|
||||
lines = contents.split(/\r*\n/);
|
||||
lines.forEach(function(line) {
|
||||
var matched = line.match(regex);
|
||||
if ((options.inverse && !matched) || (!options.inverse && matched))
|
||||
grep += line + '\n';
|
||||
});
|
||||
});
|
||||
|
||||
return common.ShellString(grep);
|
||||
}
|
||||
module.exports = _grep;
|
||||
126
bin/node_modules/shelljs/src/ls.js
generated
vendored
Normal file
126
bin/node_modules/shelljs/src/ls.js
generated
vendored
Normal file
@@ -0,0 +1,126 @@
|
||||
var path = require('path');
|
||||
var fs = require('fs');
|
||||
var common = require('./common');
|
||||
var _cd = require('./cd');
|
||||
var _pwd = require('./pwd');
|
||||
|
||||
//@
|
||||
//@ ### ls([options ,] path [,path ...])
|
||||
//@ ### ls([options ,] path_array)
|
||||
//@ Available options:
|
||||
//@
|
||||
//@ + `-R`: recursive
|
||||
//@ + `-A`: all files (include files beginning with `.`, except for `.` and `..`)
|
||||
//@
|
||||
//@ Examples:
|
||||
//@
|
||||
//@ ```javascript
|
||||
//@ ls('projs/*.js');
|
||||
//@ ls('-R', '/users/me', '/tmp');
|
||||
//@ ls('-R', ['/users/me', '/tmp']); // same as above
|
||||
//@ ```
|
||||
//@
|
||||
//@ Returns array of files in the given path, or in current directory if no path provided.
|
||||
function _ls(options, paths) {
|
||||
options = common.parseOptions(options, {
|
||||
'R': 'recursive',
|
||||
'A': 'all',
|
||||
'a': 'all_deprecated'
|
||||
});
|
||||
|
||||
if (options.all_deprecated) {
|
||||
// We won't support the -a option as it's hard to image why it's useful
|
||||
// (it includes '.' and '..' in addition to '.*' files)
|
||||
// For backwards compatibility we'll dump a deprecated message and proceed as before
|
||||
common.log('ls: Option -a is deprecated. Use -A instead');
|
||||
options.all = true;
|
||||
}
|
||||
|
||||
if (!paths)
|
||||
paths = ['.'];
|
||||
else if (typeof paths === 'object')
|
||||
paths = paths; // assume array
|
||||
else if (typeof paths === 'string')
|
||||
paths = [].slice.call(arguments, 1);
|
||||
|
||||
var list = [];
|
||||
|
||||
// Conditionally pushes file to list - returns true if pushed, false otherwise
|
||||
// (e.g. prevents hidden files to be included unless explicitly told so)
|
||||
function pushFile(file, query) {
|
||||
// hidden file?
|
||||
if (path.basename(file)[0] === '.') {
|
||||
// not explicitly asking for hidden files?
|
||||
if (!options.all && !(path.basename(query)[0] === '.' && path.basename(query).length > 1))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (common.platform === 'win')
|
||||
file = file.replace(/\\/g, '/');
|
||||
|
||||
list.push(file);
|
||||
return true;
|
||||
}
|
||||
|
||||
paths.forEach(function(p) {
|
||||
if (fs.existsSync(p)) {
|
||||
var stats = fs.statSync(p);
|
||||
// Simple file?
|
||||
if (stats.isFile()) {
|
||||
pushFile(p, p);
|
||||
return; // continue
|
||||
}
|
||||
|
||||
// Simple dir?
|
||||
if (stats.isDirectory()) {
|
||||
// Iterate over p contents
|
||||
fs.readdirSync(p).forEach(function(file) {
|
||||
if (!pushFile(file, p))
|
||||
return;
|
||||
|
||||
// Recursive?
|
||||
if (options.recursive) {
|
||||
var oldDir = _pwd();
|
||||
_cd('', p);
|
||||
if (fs.statSync(file).isDirectory())
|
||||
list = list.concat(_ls('-R'+(options.all?'A':''), file+'/*'));
|
||||
_cd('', oldDir);
|
||||
}
|
||||
});
|
||||
return; // continue
|
||||
}
|
||||
}
|
||||
|
||||
// p does not exist - possible wildcard present
|
||||
|
||||
var basename = path.basename(p);
|
||||
var dirname = path.dirname(p);
|
||||
// Wildcard present on an existing dir? (e.g. '/tmp/*.js')
|
||||
if (basename.search(/\*/) > -1 && fs.existsSync(dirname) && fs.statSync(dirname).isDirectory) {
|
||||
// Escape special regular expression chars
|
||||
var regexp = basename.replace(/(\^|\$|\(|\)|<|>|\[|\]|\{|\}|\.|\+|\?)/g, '\\$1');
|
||||
// Translates wildcard into regex
|
||||
regexp = '^' + regexp.replace(/\*/g, '.*') + '$';
|
||||
// Iterate over directory contents
|
||||
fs.readdirSync(dirname).forEach(function(file) {
|
||||
if (file.match(new RegExp(regexp))) {
|
||||
if (!pushFile(path.normalize(dirname+'/'+file), basename))
|
||||
return;
|
||||
|
||||
// Recursive?
|
||||
if (options.recursive) {
|
||||
var pp = dirname + '/' + file;
|
||||
if (fs.lstatSync(pp).isDirectory())
|
||||
list = list.concat(_ls('-R'+(options.all?'A':''), pp+'/*'));
|
||||
} // recursive
|
||||
} // if file matches
|
||||
}); // forEach
|
||||
return;
|
||||
}
|
||||
|
||||
common.error('no such file or directory: ' + p, true);
|
||||
});
|
||||
|
||||
return list;
|
||||
}
|
||||
module.exports = _ls;
|
||||
68
bin/node_modules/shelljs/src/mkdir.js
generated
vendored
Normal file
68
bin/node_modules/shelljs/src/mkdir.js
generated
vendored
Normal file
@@ -0,0 +1,68 @@
|
||||
var common = require('./common');
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
|
||||
// Recursively creates 'dir'
|
||||
function mkdirSyncRecursive(dir) {
|
||||
var baseDir = path.dirname(dir);
|
||||
|
||||
// Base dir exists, no recursion necessary
|
||||
if (fs.existsSync(baseDir)) {
|
||||
fs.mkdirSync(dir, parseInt('0777', 8));
|
||||
return;
|
||||
}
|
||||
|
||||
// Base dir does not exist, go recursive
|
||||
mkdirSyncRecursive(baseDir);
|
||||
|
||||
// Base dir created, can create dir
|
||||
fs.mkdirSync(dir, parseInt('0777', 8));
|
||||
}
|
||||
|
||||
//@
|
||||
//@ ### mkdir([options ,] dir [, dir ...])
|
||||
//@ ### mkdir([options ,] dir_array)
|
||||
//@ Available options:
|
||||
//@
|
||||
//@ + `p`: full path (will create intermediate dirs if necessary)
|
||||
//@
|
||||
//@ Examples:
|
||||
//@
|
||||
//@ ```javascript
|
||||
//@ mkdir('-p', '/tmp/a/b/c/d', '/tmp/e/f/g');
|
||||
//@ mkdir('-p', ['/tmp/a/b/c/d', '/tmp/e/f/g']); // same as above
|
||||
//@ ```
|
||||
//@
|
||||
//@ Creates directories.
|
||||
function _mkdir(options, dirs) {
|
||||
options = common.parseOptions(options, {
|
||||
'p': 'fullpath'
|
||||
});
|
||||
if (!dirs)
|
||||
common.error('no paths given');
|
||||
|
||||
if (typeof dirs === 'string')
|
||||
dirs = [].slice.call(arguments, 1);
|
||||
// if it's array leave it as it is
|
||||
|
||||
dirs.forEach(function(dir) {
|
||||
if (fs.existsSync(dir)) {
|
||||
if (!options.fullpath)
|
||||
common.error('path already exists: ' + dir, true);
|
||||
return; // skip dir
|
||||
}
|
||||
|
||||
// Base dir does not exist, and no -p option given
|
||||
var baseDir = path.dirname(dir);
|
||||
if (!fs.existsSync(baseDir) && !options.fullpath) {
|
||||
common.error('no such file or directory: ' + baseDir, true);
|
||||
return; // skip dir
|
||||
}
|
||||
|
||||
if (options.fullpath)
|
||||
mkdirSyncRecursive(dir);
|
||||
else
|
||||
fs.mkdirSync(dir, parseInt('0777', 8));
|
||||
});
|
||||
} // mkdir
|
||||
module.exports = _mkdir;
|
||||
80
bin/node_modules/shelljs/src/mv.js
generated
vendored
Normal file
80
bin/node_modules/shelljs/src/mv.js
generated
vendored
Normal file
@@ -0,0 +1,80 @@
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
var common = require('./common');
|
||||
|
||||
//@
|
||||
//@ ### mv(source [, source ...], dest')
|
||||
//@ ### mv(source_array, dest')
|
||||
//@ Available options:
|
||||
//@
|
||||
//@ + `f`: force
|
||||
//@
|
||||
//@ Examples:
|
||||
//@
|
||||
//@ ```javascript
|
||||
//@ mv('-f', 'file', 'dir/');
|
||||
//@ mv('file1', 'file2', 'dir/');
|
||||
//@ mv(['file1', 'file2'], 'dir/'); // same as above
|
||||
//@ ```
|
||||
//@
|
||||
//@ Moves files. The wildcard `*` is accepted.
|
||||
function _mv(options, sources, dest) {
|
||||
options = common.parseOptions(options, {
|
||||
'f': 'force'
|
||||
});
|
||||
|
||||
// Get sources, dest
|
||||
if (arguments.length < 3) {
|
||||
common.error('missing <source> and/or <dest>');
|
||||
} else if (arguments.length > 3) {
|
||||
sources = [].slice.call(arguments, 1, arguments.length - 1);
|
||||
dest = arguments[arguments.length - 1];
|
||||
} else if (typeof sources === 'string') {
|
||||
sources = [sources];
|
||||
} else if ('length' in sources) {
|
||||
sources = sources; // no-op for array
|
||||
} else {
|
||||
common.error('invalid arguments');
|
||||
}
|
||||
|
||||
sources = common.expand(sources);
|
||||
|
||||
var exists = fs.existsSync(dest),
|
||||
stats = exists && fs.statSync(dest);
|
||||
|
||||
// Dest is not existing dir, but multiple sources given
|
||||
if ((!exists || !stats.isDirectory()) && sources.length > 1)
|
||||
common.error('dest is not a directory (too many sources)');
|
||||
|
||||
// Dest is an existing file, but no -f given
|
||||
if (exists && stats.isFile() && !options.force)
|
||||
common.error('dest file already exists: ' + dest);
|
||||
|
||||
sources.forEach(function(src) {
|
||||
if (!fs.existsSync(src)) {
|
||||
common.error('no such file or directory: '+src, true);
|
||||
return; // skip file
|
||||
}
|
||||
|
||||
// If here, src exists
|
||||
|
||||
// When copying to '/path/dir':
|
||||
// thisDest = '/path/dir/file1'
|
||||
var thisDest = dest;
|
||||
if (fs.existsSync(dest) && fs.statSync(dest).isDirectory())
|
||||
thisDest = path.normalize(dest + '/' + path.basename(src));
|
||||
|
||||
if (fs.existsSync(thisDest) && !options.force) {
|
||||
common.error('dest file already exists: ' + thisDest, true);
|
||||
return; // skip file
|
||||
}
|
||||
|
||||
if (path.resolve(src) === path.dirname(path.resolve(thisDest))) {
|
||||
common.error('cannot move to self: '+src, true);
|
||||
return; // skip file
|
||||
}
|
||||
|
||||
fs.renameSync(src, thisDest);
|
||||
}); // forEach(src)
|
||||
} // mv
|
||||
module.exports = _mv;
|
||||
1
bin/node_modules/shelljs/src/popd.js
generated
vendored
Normal file
1
bin/node_modules/shelljs/src/popd.js
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
// see dirs.js
|
||||
1
bin/node_modules/shelljs/src/pushd.js
generated
vendored
Normal file
1
bin/node_modules/shelljs/src/pushd.js
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
// see dirs.js
|
||||
11
bin/node_modules/shelljs/src/pwd.js
generated
vendored
Normal file
11
bin/node_modules/shelljs/src/pwd.js
generated
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
var path = require('path');
|
||||
var common = require('./common');
|
||||
|
||||
//@
|
||||
//@ ### pwd()
|
||||
//@ Returns the current directory.
|
||||
function _pwd(options) {
|
||||
var pwd = path.resolve(process.cwd());
|
||||
return common.ShellString(pwd);
|
||||
}
|
||||
module.exports = _pwd;
|
||||
145
bin/node_modules/shelljs/src/rm.js
generated
vendored
Normal file
145
bin/node_modules/shelljs/src/rm.js
generated
vendored
Normal file
@@ -0,0 +1,145 @@
|
||||
var common = require('./common');
|
||||
var fs = require('fs');
|
||||
|
||||
// Recursively removes 'dir'
|
||||
// Adapted from https://github.com/ryanmcgrath/wrench-js
|
||||
//
|
||||
// Copyright (c) 2010 Ryan McGrath
|
||||
// Copyright (c) 2012 Artur Adib
|
||||
//
|
||||
// Licensed under the MIT License
|
||||
// http://www.opensource.org/licenses/mit-license.php
|
||||
function rmdirSyncRecursive(dir, force) {
|
||||
var files;
|
||||
|
||||
files = fs.readdirSync(dir);
|
||||
|
||||
// Loop through and delete everything in the sub-tree after checking it
|
||||
for(var i = 0; i < files.length; i++) {
|
||||
var file = dir + "/" + files[i],
|
||||
currFile = fs.lstatSync(file);
|
||||
|
||||
if(currFile.isDirectory()) { // Recursive function back to the beginning
|
||||
rmdirSyncRecursive(file, force);
|
||||
}
|
||||
|
||||
else if(currFile.isSymbolicLink()) { // Unlink symlinks
|
||||
if (force || isWriteable(file)) {
|
||||
try {
|
||||
common.unlinkSync(file);
|
||||
} catch (e) {
|
||||
common.error('could not remove file (code '+e.code+'): ' + file, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else // Assume it's a file - perhaps a try/catch belongs here?
|
||||
if (force || isWriteable(file)) {
|
||||
try {
|
||||
common.unlinkSync(file);
|
||||
} catch (e) {
|
||||
common.error('could not remove file (code '+e.code+'): ' + file, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Now that we know everything in the sub-tree has been deleted, we can delete the main directory.
|
||||
// Huzzah for the shopkeep.
|
||||
|
||||
var result;
|
||||
try {
|
||||
result = fs.rmdirSync(dir);
|
||||
} catch(e) {
|
||||
common.error('could not remove directory (code '+e.code+'): ' + dir, true);
|
||||
}
|
||||
|
||||
return result;
|
||||
} // rmdirSyncRecursive
|
||||
|
||||
// Hack to determine if file has write permissions for current user
|
||||
// Avoids having to check user, group, etc, but it's probably slow
|
||||
function isWriteable(file) {
|
||||
var writePermission = true;
|
||||
try {
|
||||
var __fd = fs.openSync(file, 'a');
|
||||
fs.closeSync(__fd);
|
||||
} catch(e) {
|
||||
writePermission = false;
|
||||
}
|
||||
|
||||
return writePermission;
|
||||
}
|
||||
|
||||
//@
|
||||
//@ ### rm([options ,] file [, file ...])
|
||||
//@ ### rm([options ,] file_array)
|
||||
//@ Available options:
|
||||
//@
|
||||
//@ + `-f`: force
|
||||
//@ + `-r, -R`: recursive
|
||||
//@
|
||||
//@ Examples:
|
||||
//@
|
||||
//@ ```javascript
|
||||
//@ rm('-rf', '/tmp/*');
|
||||
//@ rm('some_file.txt', 'another_file.txt');
|
||||
//@ rm(['some_file.txt', 'another_file.txt']); // same as above
|
||||
//@ ```
|
||||
//@
|
||||
//@ Removes files. The wildcard `*` is accepted.
|
||||
function _rm(options, files) {
|
||||
options = common.parseOptions(options, {
|
||||
'f': 'force',
|
||||
'r': 'recursive',
|
||||
'R': 'recursive'
|
||||
});
|
||||
if (!files)
|
||||
common.error('no paths given');
|
||||
|
||||
if (typeof files === 'string')
|
||||
files = [].slice.call(arguments, 1);
|
||||
// if it's array leave it as it is
|
||||
|
||||
files = common.expand(files);
|
||||
|
||||
files.forEach(function(file) {
|
||||
if (!fs.existsSync(file)) {
|
||||
// Path does not exist, no force flag given
|
||||
if (!options.force)
|
||||
common.error('no such file or directory: '+file, true);
|
||||
|
||||
return; // skip file
|
||||
}
|
||||
|
||||
// If here, path exists
|
||||
|
||||
var stats = fs.lstatSync(file);
|
||||
if (stats.isFile() || stats.isSymbolicLink()) {
|
||||
|
||||
// Do not check for file writing permissions
|
||||
if (options.force) {
|
||||
common.unlinkSync(file);
|
||||
return;
|
||||
}
|
||||
|
||||
if (isWriteable(file))
|
||||
common.unlinkSync(file);
|
||||
else
|
||||
common.error('permission denied: '+file, true);
|
||||
|
||||
return;
|
||||
} // simple file
|
||||
|
||||
// Path is an existing directory, but no -r flag given
|
||||
if (stats.isDirectory() && !options.recursive) {
|
||||
common.error('path is a directory', true);
|
||||
return; // skip path
|
||||
}
|
||||
|
||||
// Recursively remove existing directory
|
||||
if (stats.isDirectory() && options.recursive) {
|
||||
rmdirSyncRecursive(file, options.force);
|
||||
}
|
||||
}); // forEach(file)
|
||||
} // rm
|
||||
module.exports = _rm;
|
||||
43
bin/node_modules/shelljs/src/sed.js
generated
vendored
Normal file
43
bin/node_modules/shelljs/src/sed.js
generated
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
var common = require('./common');
|
||||
var fs = require('fs');
|
||||
|
||||
//@
|
||||
//@ ### sed([options ,] search_regex, replace_str, file)
|
||||
//@ Available options:
|
||||
//@
|
||||
//@ + `-i`: Replace contents of 'file' in-place. _Note that no backups will be created!_
|
||||
//@
|
||||
//@ Examples:
|
||||
//@
|
||||
//@ ```javascript
|
||||
//@ sed('-i', 'PROGRAM_VERSION', 'v0.1.3', 'source.js');
|
||||
//@ sed(/.*DELETE_THIS_LINE.*\n/, '', 'source.js');
|
||||
//@ ```
|
||||
//@
|
||||
//@ Reads an input string from `file` and performs a JavaScript `replace()` on the input
|
||||
//@ using the given search regex and replacement string. Returns the new string after replacement.
|
||||
function _sed(options, regex, replacement, file) {
|
||||
options = common.parseOptions(options, {
|
||||
'i': 'inplace'
|
||||
});
|
||||
|
||||
if (typeof replacement === 'string')
|
||||
replacement = replacement; // no-op
|
||||
else if (typeof replacement === 'number')
|
||||
replacement = replacement.toString(); // fallback
|
||||
else
|
||||
common.error('invalid replacement string');
|
||||
|
||||
if (!file)
|
||||
common.error('no file given');
|
||||
|
||||
if (!fs.existsSync(file))
|
||||
common.error('no such file or directory: ' + file);
|
||||
|
||||
var result = fs.readFileSync(file, 'utf8').replace(regex, replacement);
|
||||
if (options.inplace)
|
||||
fs.writeFileSync(file, result, 'utf8');
|
||||
|
||||
return common.ShellString(result);
|
||||
}
|
||||
module.exports = _sed;
|
||||
56
bin/node_modules/shelljs/src/tempdir.js
generated
vendored
Normal file
56
bin/node_modules/shelljs/src/tempdir.js
generated
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
var common = require('./common');
|
||||
var os = require('os');
|
||||
var fs = require('fs');
|
||||
|
||||
// Returns false if 'dir' is not a writeable directory, 'dir' otherwise
|
||||
function writeableDir(dir) {
|
||||
if (!dir || !fs.existsSync(dir))
|
||||
return false;
|
||||
|
||||
if (!fs.statSync(dir).isDirectory())
|
||||
return false;
|
||||
|
||||
var testFile = dir+'/'+common.randomFileName();
|
||||
try {
|
||||
fs.writeFileSync(testFile, ' ');
|
||||
common.unlinkSync(testFile);
|
||||
return dir;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//@
|
||||
//@ ### tempdir()
|
||||
//@
|
||||
//@ Examples:
|
||||
//@
|
||||
//@ ```javascript
|
||||
//@ var tmp = tempdir(); // "/tmp" for most *nix platforms
|
||||
//@ ```
|
||||
//@
|
||||
//@ Searches and returns string containing a writeable, platform-dependent temporary directory.
|
||||
//@ Follows Python's [tempfile algorithm](http://docs.python.org/library/tempfile.html#tempfile.tempdir).
|
||||
function _tempDir() {
|
||||
var state = common.state;
|
||||
if (state.tempDir)
|
||||
return state.tempDir; // from cache
|
||||
|
||||
state.tempDir = writeableDir(os.tempDir && os.tempDir()) || // node 0.8+
|
||||
writeableDir(process.env['TMPDIR']) ||
|
||||
writeableDir(process.env['TEMP']) ||
|
||||
writeableDir(process.env['TMP']) ||
|
||||
writeableDir(process.env['Wimp$ScrapDir']) || // RiscOS
|
||||
writeableDir('C:\\TEMP') || // Windows
|
||||
writeableDir('C:\\TMP') || // Windows
|
||||
writeableDir('\\TEMP') || // Windows
|
||||
writeableDir('\\TMP') || // Windows
|
||||
writeableDir('/tmp') ||
|
||||
writeableDir('/var/tmp') ||
|
||||
writeableDir('/usr/tmp') ||
|
||||
writeableDir('.'); // last resort
|
||||
|
||||
return state.tempDir;
|
||||
}
|
||||
module.exports = _tempDir;
|
||||
85
bin/node_modules/shelljs/src/test.js
generated
vendored
Normal file
85
bin/node_modules/shelljs/src/test.js
generated
vendored
Normal file
@@ -0,0 +1,85 @@
|
||||
var common = require('./common');
|
||||
var fs = require('fs');
|
||||
|
||||
//@
|
||||
//@ ### test(expression)
|
||||
//@ Available expression primaries:
|
||||
//@
|
||||
//@ + `'-b', 'path'`: true if path is a block device
|
||||
//@ + `'-c', 'path'`: true if path is a character device
|
||||
//@ + `'-d', 'path'`: true if path is a directory
|
||||
//@ + `'-e', 'path'`: true if path exists
|
||||
//@ + `'-f', 'path'`: true if path is a regular file
|
||||
//@ + `'-L', 'path'`: true if path is a symboilc link
|
||||
//@ + `'-p', 'path'`: true if path is a pipe (FIFO)
|
||||
//@ + `'-S', 'path'`: true if path is a socket
|
||||
//@
|
||||
//@ Examples:
|
||||
//@
|
||||
//@ ```javascript
|
||||
//@ if (test('-d', path)) { /* do something with dir */ };
|
||||
//@ if (!test('-f', path)) continue; // skip if it's a regular file
|
||||
//@ ```
|
||||
//@
|
||||
//@ Evaluates expression using the available primaries and returns corresponding value.
|
||||
function _test(options, path) {
|
||||
if (!path)
|
||||
common.error('no path given');
|
||||
|
||||
// hack - only works with unary primaries
|
||||
options = common.parseOptions(options, {
|
||||
'b': 'block',
|
||||
'c': 'character',
|
||||
'd': 'directory',
|
||||
'e': 'exists',
|
||||
'f': 'file',
|
||||
'L': 'link',
|
||||
'p': 'pipe',
|
||||
'S': 'socket'
|
||||
});
|
||||
|
||||
var canInterpret = false;
|
||||
for (var key in options)
|
||||
if (options[key] === true) {
|
||||
canInterpret = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!canInterpret)
|
||||
common.error('could not interpret expression');
|
||||
|
||||
if (options.link) {
|
||||
try {
|
||||
return fs.lstatSync(path).isSymbolicLink();
|
||||
} catch(e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!fs.existsSync(path))
|
||||
return false;
|
||||
|
||||
if (options.exists)
|
||||
return true;
|
||||
|
||||
var stats = fs.statSync(path);
|
||||
|
||||
if (options.block)
|
||||
return stats.isBlockDevice();
|
||||
|
||||
if (options.character)
|
||||
return stats.isCharacterDevice();
|
||||
|
||||
if (options.directory)
|
||||
return stats.isDirectory();
|
||||
|
||||
if (options.file)
|
||||
return stats.isFile();
|
||||
|
||||
if (options.pipe)
|
||||
return stats.isFIFO();
|
||||
|
||||
if (options.socket)
|
||||
return stats.isSocket();
|
||||
} // test
|
||||
module.exports = _test;
|
||||
29
bin/node_modules/shelljs/src/to.js
generated
vendored
Normal file
29
bin/node_modules/shelljs/src/to.js
generated
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
var common = require('./common');
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
|
||||
//@
|
||||
//@ ### 'string'.to(file)
|
||||
//@
|
||||
//@ Examples:
|
||||
//@
|
||||
//@ ```javascript
|
||||
//@ cat('input.txt').to('output.txt');
|
||||
//@ ```
|
||||
//@
|
||||
//@ Analogous to the redirection operator `>` in Unix, but works with JavaScript strings (such as
|
||||
//@ those returned by `cat`, `grep`, etc). _Like Unix redirections, `to()` will overwrite any existing file!_
|
||||
function _to(options, file) {
|
||||
if (!file)
|
||||
common.error('wrong arguments');
|
||||
|
||||
if (!fs.existsSync( path.dirname(file) ))
|
||||
common.error('no such file or directory: ' + path.dirname(file));
|
||||
|
||||
try {
|
||||
fs.writeFileSync(file, this.toString(), 'utf8');
|
||||
} catch(e) {
|
||||
common.error('could not write to file (code '+e.code+'): '+file, true);
|
||||
}
|
||||
}
|
||||
module.exports = _to;
|
||||
29
bin/node_modules/shelljs/src/toEnd.js
generated
vendored
Normal file
29
bin/node_modules/shelljs/src/toEnd.js
generated
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
var common = require('./common');
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
|
||||
//@
|
||||
//@ ### 'string'.toEnd(file)
|
||||
//@
|
||||
//@ Examples:
|
||||
//@
|
||||
//@ ```javascript
|
||||
//@ cat('input.txt').toEnd('output.txt');
|
||||
//@ ```
|
||||
//@
|
||||
//@ Analogous to the redirect-and-append operator `>>` in Unix, but works with JavaScript strings (such as
|
||||
//@ those returned by `cat`, `grep`, etc).
|
||||
function _toEnd(options, file) {
|
||||
if (!file)
|
||||
common.error('wrong arguments');
|
||||
|
||||
if (!fs.existsSync( path.dirname(file) ))
|
||||
common.error('no such file or directory: ' + path.dirname(file));
|
||||
|
||||
try {
|
||||
fs.appendFileSync(file, this.toString(), 'utf8');
|
||||
} catch(e) {
|
||||
common.error('could not append to file (code '+e.code+'): '+file, true);
|
||||
}
|
||||
}
|
||||
module.exports = _toEnd;
|
||||
79
bin/node_modules/shelljs/src/which.js
generated
vendored
Normal file
79
bin/node_modules/shelljs/src/which.js
generated
vendored
Normal file
@@ -0,0 +1,79 @@
|
||||
var common = require('./common');
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
|
||||
// Cross-platform method for splitting environment PATH variables
|
||||
function splitPath(p) {
|
||||
for (i=1;i<2;i++) {}
|
||||
|
||||
if (!p)
|
||||
return [];
|
||||
|
||||
if (common.platform === 'win')
|
||||
return p.split(';');
|
||||
else
|
||||
return p.split(':');
|
||||
}
|
||||
|
||||
//@
|
||||
//@ ### which(command)
|
||||
//@
|
||||
//@ Examples:
|
||||
//@
|
||||
//@ ```javascript
|
||||
//@ var nodeExec = which('node');
|
||||
//@ ```
|
||||
//@
|
||||
//@ Searches for `command` in the system's PATH. On Windows looks for `.exe`, `.cmd`, and `.bat` extensions.
|
||||
//@ Returns string containing the absolute path to the command.
|
||||
function _which(options, cmd) {
|
||||
if (!cmd)
|
||||
common.error('must specify command');
|
||||
|
||||
var pathEnv = process.env.path || process.env.Path || process.env.PATH,
|
||||
pathArray = splitPath(pathEnv),
|
||||
where = null;
|
||||
|
||||
// No relative/absolute paths provided?
|
||||
if (cmd.search(/\//) === -1) {
|
||||
// Search for command in PATH
|
||||
pathArray.forEach(function(dir) {
|
||||
if (where)
|
||||
return; // already found it
|
||||
|
||||
var attempt = path.resolve(dir + '/' + cmd);
|
||||
if (fs.existsSync(attempt)) {
|
||||
where = attempt;
|
||||
return;
|
||||
}
|
||||
|
||||
if (common.platform === 'win') {
|
||||
var baseAttempt = attempt;
|
||||
attempt = baseAttempt + '.exe';
|
||||
if (fs.existsSync(attempt)) {
|
||||
where = attempt;
|
||||
return;
|
||||
}
|
||||
attempt = baseAttempt + '.cmd';
|
||||
if (fs.existsSync(attempt)) {
|
||||
where = attempt;
|
||||
return;
|
||||
}
|
||||
attempt = baseAttempt + '.bat';
|
||||
if (fs.existsSync(attempt)) {
|
||||
where = attempt;
|
||||
return;
|
||||
}
|
||||
} // if 'win'
|
||||
});
|
||||
}
|
||||
|
||||
// Command not found anywhere?
|
||||
if (!fs.existsSync(cmd) && !where)
|
||||
return null;
|
||||
|
||||
where = where || path.resolve(cmd);
|
||||
|
||||
return common.ShellString(where);
|
||||
}
|
||||
module.exports = _which;
|
||||
23
bin/node_modules/which/LICENSE
generated
vendored
Normal file
23
bin/node_modules/which/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
Copyright 2009, 2010, 2011 Isaac Z. Schlueter.
|
||||
All rights reserved.
|
||||
|
||||
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.
|
||||
5
bin/node_modules/which/README.md
generated
vendored
Normal file
5
bin/node_modules/which/README.md
generated
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
The "which" util from npm's guts.
|
||||
|
||||
Finds the first instance of a specified executable in the PATH
|
||||
environment variable. Does not cache the results, so `hash -r` is not
|
||||
needed when the PATH changes.
|
||||
14
bin/node_modules/which/bin/which
generated
vendored
Executable file
14
bin/node_modules/which/bin/which
generated
vendored
Executable file
@@ -0,0 +1,14 @@
|
||||
#!/usr/bin/env node
|
||||
var which = require("../")
|
||||
if (process.argv.length < 3) {
|
||||
console.error("Usage: which <thing>")
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
which(process.argv[2], function (er, thing) {
|
||||
if (er) {
|
||||
console.error(er.message)
|
||||
process.exit(er.errno || 127)
|
||||
}
|
||||
console.log(thing)
|
||||
})
|
||||
31
bin/node_modules/which/package.json
generated
vendored
Normal file
31
bin/node_modules/which/package.json
generated
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"author": {
|
||||
"name": "Isaac Z. Schlueter",
|
||||
"email": "i@izs.me",
|
||||
"url": "http://blog.izs.me"
|
||||
},
|
||||
"name": "which",
|
||||
"description": "Like which(1) unix command. Find the first instance of an executable in the PATH.",
|
||||
"version": "1.0.5",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/isaacs/node-which.git"
|
||||
},
|
||||
"main": "which.js",
|
||||
"bin": {
|
||||
"which": "./bin/which"
|
||||
},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
},
|
||||
"dependencies": {},
|
||||
"devDependencies": {},
|
||||
"readme": "The \"which\" util from npm's guts.\n\nFinds the first instance of a specified executable in the PATH\nenvironment variable. Does not cache the results, so `hash -r` is not\nneeded when the PATH changes.\n",
|
||||
"readmeFilename": "README.md",
|
||||
"bugs": {
|
||||
"url": "https://github.com/isaacs/node-which/issues"
|
||||
},
|
||||
"homepage": "https://github.com/isaacs/node-which",
|
||||
"_id": "which@1.0.5",
|
||||
"_from": "which@"
|
||||
}
|
||||
104
bin/node_modules/which/which.js
generated
vendored
Normal file
104
bin/node_modules/which/which.js
generated
vendored
Normal file
@@ -0,0 +1,104 @@
|
||||
module.exports = which
|
||||
which.sync = whichSync
|
||||
|
||||
var path = require("path")
|
||||
, fs
|
||||
, COLON = process.platform === "win32" ? ";" : ":"
|
||||
, isExe
|
||||
|
||||
try {
|
||||
fs = require("graceful-fs")
|
||||
} catch (ex) {
|
||||
fs = require("fs")
|
||||
}
|
||||
|
||||
if (process.platform == "win32") {
|
||||
// On windows, there is no good way to check that a file is executable
|
||||
isExe = function isExe () { return true }
|
||||
} else {
|
||||
isExe = function isExe (mod, uid, gid) {
|
||||
//console.error(mod, uid, gid);
|
||||
//console.error("isExe?", (mod & 0111).toString(8))
|
||||
var ret = (mod & 0001)
|
||||
|| (mod & 0010) && process.getgid && gid === process.getgid()
|
||||
|| (mod & 0100) && process.getuid && uid === process.getuid()
|
||||
//console.error("isExe?", ret)
|
||||
return ret
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
function which (cmd, cb) {
|
||||
if (isAbsolute(cmd)) return cb(null, cmd)
|
||||
var pathEnv = (process.env.PATH || "").split(COLON)
|
||||
, pathExt = [""]
|
||||
if (process.platform === "win32") {
|
||||
pathEnv.push(process.cwd())
|
||||
pathExt = (process.env.PATHEXT || ".EXE").split(COLON)
|
||||
if (cmd.indexOf(".") !== -1) pathExt.unshift("")
|
||||
}
|
||||
//console.error("pathEnv", pathEnv)
|
||||
;(function F (i, l) {
|
||||
if (i === l) return cb(new Error("not found: "+cmd))
|
||||
var p = path.resolve(pathEnv[i], cmd)
|
||||
;(function E (ii, ll) {
|
||||
if (ii === ll) return F(i + 1, l)
|
||||
var ext = pathExt[ii]
|
||||
//console.error(p + ext)
|
||||
fs.stat(p + ext, function (er, stat) {
|
||||
if (!er &&
|
||||
stat &&
|
||||
stat.isFile() &&
|
||||
isExe(stat.mode, stat.uid, stat.gid)) {
|
||||
//console.error("yes, exe!", p + ext)
|
||||
return cb(null, p + ext)
|
||||
}
|
||||
return E(ii + 1, ll)
|
||||
})
|
||||
})(0, pathExt.length)
|
||||
})(0, pathEnv.length)
|
||||
}
|
||||
|
||||
function whichSync (cmd) {
|
||||
if (isAbsolute(cmd)) return cmd
|
||||
var pathEnv = (process.env.PATH || "").split(COLON)
|
||||
, pathExt = [""]
|
||||
if (process.platform === "win32") {
|
||||
pathEnv.push(process.cwd())
|
||||
pathExt = (process.env.PATHEXT || ".EXE").split(COLON)
|
||||
if (cmd.indexOf(".") !== -1) pathExt.unshift("")
|
||||
}
|
||||
for (var i = 0, l = pathEnv.length; i < l; i ++) {
|
||||
var p = path.join(pathEnv[i], cmd)
|
||||
for (var j = 0, ll = pathExt.length; j < ll; j ++) {
|
||||
var cur = p + pathExt[j]
|
||||
var stat
|
||||
try { stat = fs.statSync(cur) } catch (ex) {}
|
||||
if (stat &&
|
||||
stat.isFile() &&
|
||||
isExe(stat.mode, stat.uid, stat.gid)) return cur
|
||||
}
|
||||
}
|
||||
throw new Error("not found: "+cmd)
|
||||
}
|
||||
|
||||
var isAbsolute = process.platform === "win32" ? absWin : absUnix
|
||||
|
||||
function absWin (p) {
|
||||
if (absUnix(p)) return true
|
||||
// pull off the device/UNC bit from a windows path.
|
||||
// from node's lib/path.js
|
||||
var splitDeviceRe =
|
||||
/^([a-zA-Z]:|[\\\/]{2}[^\\\/]+[\\\/][^\\\/]+)?([\\\/])?/
|
||||
, result = splitDeviceRe.exec(p)
|
||||
, device = result[1] || ''
|
||||
, isUnc = device && device.charAt(1) !== ':'
|
||||
, isAbsolute = !!result[2] || isUnc // UNC paths are always absolute
|
||||
|
||||
return isAbsolute
|
||||
}
|
||||
|
||||
function absUnix (p) {
|
||||
return p.charAt(0) === "/" || p === ""
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import org.xml.sax.SAXException;
|
||||
import java.io.IOException;
|
||||
|
||||
public class ApplicationInfo {
|
||||
private static void parseAndroidManifest(String path) {
|
||||
// System.out.println(path);
|
||||
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
|
||||
Document dom;
|
||||
try {
|
||||
DocumentBuilder db = dbf.newDocumentBuilder();
|
||||
dom = db.parse(path);
|
||||
|
||||
// getting package information
|
||||
Element manifest = dom.getDocumentElement();
|
||||
String pakkage = manifest.getAttribute("package");
|
||||
|
||||
// getting activity name
|
||||
String activity = ((Element)dom.getElementsByTagName("activity").item(0)).getAttribute("android:name");
|
||||
System.out.println(String.format("%s/.%s", pakkage, activity.replace(".", "")));
|
||||
} catch(ParserConfigurationException pce) {
|
||||
pce.printStackTrace();
|
||||
} catch(SAXException se) {
|
||||
se.printStackTrace();
|
||||
} catch(IOException ioe) {
|
||||
ioe.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
String path;
|
||||
if(args.length > 0) {
|
||||
path = args[0];
|
||||
} else {
|
||||
path = System.getProperty("user.dir") + "/../AndroidManifest.xml";
|
||||
}
|
||||
parseAndroidManifest(path);
|
||||
}
|
||||
}
|
||||
@@ -1,39 +1,41 @@
|
||||
#!/bin/bash
|
||||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance
|
||||
# with the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing,
|
||||
# software distributed under the License is distributed on an
|
||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
# KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#!/usr/bin/env node
|
||||
|
||||
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||
PROJECT_PATH=$( cd "$DIR/.." && pwd )
|
||||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
if [[ "$#" -eq 1 ]] ; then
|
||||
if [[ $1 == "--debug" ]] ; then
|
||||
$DIR/clean
|
||||
ant debug -f "$PROJECT_PATH"/build.xml
|
||||
elif [[ $1 == "--release" ]] ; then
|
||||
$DIR/clean
|
||||
ant release -f "$PROJECT_PATH"/build.xml
|
||||
elif [[ $1 == "--nobuild" ]] ; then
|
||||
echo "Skipping build..."
|
||||
else
|
||||
echo "Error : Build command '$1' not recognized."
|
||||
exit 2
|
||||
fi
|
||||
else
|
||||
echo "Warning : [ --debug | --release | --nobuild ] not specified, defaulting to --debug"
|
||||
$DIR/clean
|
||||
ant debug -f "$PROJECT_PATH"/build.xml
|
||||
fi
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
|
||||
var build = require('./lib/build'),
|
||||
reqs = require('./lib/check_reqs'),
|
||||
args = process.argv;
|
||||
|
||||
// Support basic help commands
|
||||
if(args[2] == '--help' ||
|
||||
args[2] == '/?' ||
|
||||
args[2] == '-h' ||
|
||||
args[2] == 'help' ||
|
||||
args[2] == '-help' ||
|
||||
args[2] == '/help') {
|
||||
build.help();
|
||||
} else {
|
||||
reqs.run().done(function() {
|
||||
return build.run(args.slice(2));
|
||||
}, function(err) {
|
||||
console.error(err);
|
||||
process.exit(2);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -5,14 +5,22 @@
|
||||
:: to you under the Apache License, Version 2.0 (the
|
||||
:: "License"); you may not use this file except in compliance
|
||||
:: with the License. You may obtain a copy of the License at
|
||||
::
|
||||
::
|
||||
:: http://www.apache.org/licenses/LICENSE-2.0
|
||||
::
|
||||
::
|
||||
:: Unless required by applicable law or agreed to in writing,
|
||||
:: software distributed under the License is distributed on an
|
||||
:: "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
:: KIND, either express or implied. See the License for the
|
||||
:: specific language governing permissions and limitations
|
||||
:: under the License.
|
||||
|
||||
@ECHO OFF
|
||||
%~dp0\cordova.bat build %*
|
||||
SET script_path="%~dp0build"
|
||||
IF EXIST %script_path% (
|
||||
node %script_path% %*
|
||||
) ELSE (
|
||||
ECHO.
|
||||
ECHO ERROR: Could not find 'build' script in 'cordova' folder, aborting...>&2
|
||||
EXIT /B 1
|
||||
)
|
||||
@@ -1,22 +1,44 @@
|
||||
#!/bin/bash
|
||||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance
|
||||
# with the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing,
|
||||
# software distributed under the License is distributed on an
|
||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
# KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#!/usr/bin/env node
|
||||
|
||||
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||
PROJECT_PATH=$( cd "$DIR/.." && pwd )
|
||||
echo "Cleaning project..."
|
||||
ant -f "$PROJECT_PATH/build.xml" clean
|
||||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
|
||||
var build = require('./lib/build'),
|
||||
reqs = require('./lib/check_reqs'),
|
||||
args = process.argv;
|
||||
var path = require('path');
|
||||
|
||||
// Support basic help commands
|
||||
if(args[2] == '--help' ||
|
||||
args[2] == '/?' ||
|
||||
args[2] == '-h' ||
|
||||
args[2] == 'help' ||
|
||||
args[2] == '-help' ||
|
||||
args[2] == '/help') {
|
||||
console.log('Usage: ' + path.relative(process.cwd(), process.argv[1]));
|
||||
console.log('Cleans the project directory.');
|
||||
process.exit(0);
|
||||
} else {
|
||||
reqs.run().done(function() {
|
||||
return build.runClean(args.slice(2));
|
||||
}, function(err) {
|
||||
console.error(err);
|
||||
process.exit(2);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -5,14 +5,22 @@
|
||||
:: to you under the Apache License, Version 2.0 (the
|
||||
:: "License"); you may not use this file except in compliance
|
||||
:: with the License. You may obtain a copy of the License at
|
||||
::
|
||||
::
|
||||
:: http://www.apache.org/licenses/LICENSE-2.0
|
||||
::
|
||||
::
|
||||
:: Unless required by applicable law or agreed to in writing,
|
||||
:: software distributed under the License is distributed on an
|
||||
:: "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
:: KIND, either express or implied. See the License for the
|
||||
:: specific language governing permissions and limitations
|
||||
:: under the License.
|
||||
|
||||
@ECHO OFF
|
||||
%~dp0\cordova.bat clean %*
|
||||
SET script_path="%~dp0clean"
|
||||
IF EXIST %script_path% (
|
||||
node %script_path% %*
|
||||
) ELSE (
|
||||
ECHO.
|
||||
ECHO ERROR: Could not find 'clean' script in 'cordova' folder, aborting...>&2
|
||||
EXIT /B 1
|
||||
)
|
||||
26
bin/templates/cordova/defaults.xml
Normal file
26
bin/templates/cordova/defaults.xml
Normal file
@@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
-->
|
||||
<widget xmlns = "http://www.w3.org/ns/widgets"
|
||||
id = "io.cordova.helloCordova"
|
||||
version = "2.0.0">
|
||||
|
||||
<!-- Preferences for Android -->
|
||||
<preference name="loglevel" value="DEBUG" />
|
||||
</widget>
|
||||
41
bin/templates/cordova/lib/appinfo.js
vendored
Normal file
41
bin/templates/cordova/lib/appinfo.js
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
|
||||
var path = require('path');
|
||||
var fs = require('fs');
|
||||
var cachedAppInfo = null;
|
||||
|
||||
function readAppInfoFromManifest() {
|
||||
var manifestPath = path.join(__dirname, '..', '..', 'AndroidManifest.xml');
|
||||
var manifestData = fs.readFileSync(manifestPath, {encoding:'utf8'});
|
||||
var packageName = /\bpackage\s*=\s*"(.+?)"/.exec(manifestData);
|
||||
if (!packageName) throw new Error('Could not find package name within ' + manifestPath);
|
||||
var activityTag = /<activity\b[\s\S]*<\/activity>/.exec(manifestData);
|
||||
if (!activityTag) throw new Error('Could not find <activity> within ' + manifestPath);
|
||||
var activityName = /\bandroid:name\s*=\s*"(.+?)"/.exec(activityTag);
|
||||
if (!activityName) throw new Error('Could not find android:name within ' + manifestPath);
|
||||
|
||||
return packageName[1] + '/.' + activityName[1];
|
||||
}
|
||||
|
||||
exports.getActivityName = function() {
|
||||
return cachedAppInfo = cachedAppInfo || readAppInfoFromManifest();
|
||||
};
|
||||
481
bin/templates/cordova/lib/build.js
vendored
Normal file
481
bin/templates/cordova/lib/build.js
vendored
Normal file
@@ -0,0 +1,481 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
|
||||
var shell = require('shelljs'),
|
||||
spawn = require('./spawn'),
|
||||
Q = require('q'),
|
||||
path = require('path'),
|
||||
fs = require('fs'),
|
||||
os = require('os'),
|
||||
ROOT = path.join(__dirname, '..', '..');
|
||||
var check_reqs = require('./check_reqs');
|
||||
var exec = require('./exec');
|
||||
|
||||
var LOCAL_PROPERTIES_TEMPLATE =
|
||||
'# This file is automatically generated.\n' +
|
||||
'# Do not modify this file -- YOUR CHANGES WILL BE ERASED!\n';
|
||||
|
||||
function findApks(directory) {
|
||||
var ret = [];
|
||||
if (fs.existsSync(directory)) {
|
||||
fs.readdirSync(directory).forEach(function(p) {
|
||||
if (path.extname(p) == '.apk') {
|
||||
ret.push(path.join(directory, p));
|
||||
}
|
||||
});
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
function sortFilesByDate(files) {
|
||||
return files.map(function(p) {
|
||||
return { p: p, t: fs.statSync(p).mtime };
|
||||
}).sort(function(a, b) {
|
||||
var timeDiff = b.t - a.t;
|
||||
return timeDiff === 0 ? a.p.length - b.p.length : timeDiff;
|
||||
}).map(function(p) { return p.p; });
|
||||
}
|
||||
|
||||
function findOutputApksHelper(dir, build_type, arch) {
|
||||
var ret = findApks(dir).filter(function(candidate) {
|
||||
// Need to choose between release and debug .apk.
|
||||
if (build_type === 'debug') {
|
||||
return /-debug/.exec(candidate) && !/-unaligned|-unsigned/.exec(candidate);
|
||||
}
|
||||
if (build_type === 'release') {
|
||||
return /-release/.exec(candidate) && !/-unaligned/.exec(candidate);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
ret = sortFilesByDate(ret);
|
||||
if (ret.length === 0) {
|
||||
return ret;
|
||||
}
|
||||
// Assume arch-specific build if newest api has -x86 or -arm.
|
||||
var archSpecific = !!/-x86|-arm/.exec(ret[0]);
|
||||
// And show only arch-specific ones (or non-arch-specific)
|
||||
ret = ret.filter(function(p) {
|
||||
return !!/-x86|-arm/.exec(p) == archSpecific;
|
||||
});
|
||||
if (arch && ret.length > 1) {
|
||||
ret = ret.filter(function(p) {
|
||||
return p.indexOf('-' + arch) != -1;
|
||||
});
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
function hasCustomRules() {
|
||||
return fs.existsSync(path.join(ROOT, 'custom_rules.xml'));
|
||||
}
|
||||
|
||||
function extractProjectNameFromManifest(projectPath) {
|
||||
var manifestPath = path.join(projectPath, 'AndroidManifest.xml');
|
||||
var manifestData = fs.readFileSync(manifestPath, 'utf8');
|
||||
var m = /<activity[\s\S]*?android:name\s*=\s*"(.*?)"/i.exec(manifestData);
|
||||
if (!m) {
|
||||
throw new Error('Could not find activity name in ' + manifestPath);
|
||||
}
|
||||
return m[1];
|
||||
}
|
||||
|
||||
function extractSubProjectPaths() {
|
||||
var data = fs.readFileSync(path.join(ROOT, 'project.properties'), 'utf8');
|
||||
var ret = {};
|
||||
var r = /^\s*android\.library\.reference\.\d+=(.*)(?:\s|$)/mg
|
||||
var m;
|
||||
while (m = r.exec(data)) {
|
||||
ret[m[1]] = 1;
|
||||
}
|
||||
return Object.keys(ret);
|
||||
}
|
||||
|
||||
var builders = {
|
||||
ant: {
|
||||
getArgs: function(cmd) {
|
||||
var args = [cmd, '-f', path.join(ROOT, 'build.xml')];
|
||||
// custom_rules.xml is required for incremental builds.
|
||||
if (hasCustomRules()) {
|
||||
args.push('-Dout.dir=ant-build', '-Dgen.absolute.dir=ant-gen');
|
||||
}
|
||||
return args;
|
||||
},
|
||||
|
||||
prepEnv: function() {
|
||||
return check_reqs.check_ant()
|
||||
.then(function() {
|
||||
// Copy in build.xml on each build so that:
|
||||
// A) we don't require the Android SDK at project creation time, and
|
||||
// B) we always use the SDK's latest version of it.
|
||||
var sdkDir = process.env['ANDROID_HOME'];
|
||||
var buildTemplate = fs.readFileSync(path.join(sdkDir, 'tools', 'lib', 'build.template'), 'utf8');
|
||||
function writeBuildXml(projectPath) {
|
||||
var newData = buildTemplate.replace('PROJECT_NAME', extractProjectNameFromManifest(ROOT));
|
||||
fs.writeFileSync(path.join(projectPath, 'build.xml'), newData);
|
||||
if (!fs.existsSync(path.join(projectPath, 'local.properties'))) {
|
||||
fs.writeFileSync(path.join(projectPath, 'local.properties'), LOCAL_PROPERTIES_TEMPLATE);
|
||||
}
|
||||
}
|
||||
var subProjects = extractSubProjectPaths();
|
||||
writeBuildXml(ROOT);
|
||||
for (var i = 0; i < subProjects.length; ++i) {
|
||||
writeBuildXml(path.join(ROOT, subProjects[i]));
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/*
|
||||
* Builds the project with ant.
|
||||
* Returns a promise.
|
||||
*/
|
||||
build: function(build_type) {
|
||||
// Without our custom_rules.xml, we need to clean before building.
|
||||
var ret = Q();
|
||||
if (!hasCustomRules()) {
|
||||
// clean will call check_ant() for us.
|
||||
ret = this.clean();
|
||||
}
|
||||
|
||||
var builder = this;
|
||||
var args = this.getArgs(build_type == 'debug' ? 'debug' : 'release');
|
||||
return check_reqs.check_ant()
|
||||
.then(function() {
|
||||
return spawn('ant', args);
|
||||
});
|
||||
},
|
||||
|
||||
clean: function() {
|
||||
var args = this.getArgs('clean');
|
||||
return check_reqs.check_ant()
|
||||
.then(function() {
|
||||
return spawn('ant', args);
|
||||
});
|
||||
},
|
||||
|
||||
findOutputApks: function(build_type) {
|
||||
var binDir = path.join(ROOT, hasCustomRules() ? 'ant-build' : 'bin');
|
||||
return findOutputApksHelper(binDir, build_type, null);
|
||||
}
|
||||
},
|
||||
gradle: {
|
||||
getArgs: function(cmd, arch, extraArgs) {
|
||||
if (cmd == 'release') {
|
||||
cmd = 'cdvBuildRelease';
|
||||
} else if (cmd == 'debug') {
|
||||
cmd = 'cdvBuildDebug';
|
||||
}
|
||||
var args = [cmd, '-b', path.join(ROOT, 'build.gradle')];
|
||||
if (arch) {
|
||||
args.push('-PcdvBuildArch=' + arch);
|
||||
}
|
||||
|
||||
// 10 seconds -> 6 seconds
|
||||
args.push('-Dorg.gradle.daemon=true');
|
||||
args.push.apply(args, extraArgs);
|
||||
// Shaves another 100ms, but produces a "try at own risk" warning. Not worth it (yet):
|
||||
// args.push('-Dorg.gradle.parallel=true');
|
||||
return args;
|
||||
},
|
||||
|
||||
prepEnv: function() {
|
||||
return check_reqs.check_gradle()
|
||||
.then(function() {
|
||||
// Copy the gradle wrapper on each build so that:
|
||||
// A) we don't require the Android SDK at project creation time, and
|
||||
// B) we always use the SDK's latest version of it.
|
||||
var projectPath = ROOT;
|
||||
// check_reqs ensures that this is set.
|
||||
var sdkDir = process.env['ANDROID_HOME'];
|
||||
var wrapperDir = path.join(sdkDir, 'tools', 'templates', 'gradle', 'wrapper');
|
||||
if (process.platform == 'win32') {
|
||||
shell.cp('-f', path.join(wrapperDir, 'gradlew.bat'), projectPath);
|
||||
} else {
|
||||
shell.cp('-f', path.join(wrapperDir, 'gradlew'), projectPath);
|
||||
}
|
||||
shell.rm('-rf', path.join(projectPath, 'gradle', 'wrapper'));
|
||||
shell.mkdir('-p', path.join(projectPath, 'gradle'));
|
||||
shell.cp('-r', path.join(wrapperDir, 'gradle', 'wrapper'), path.join(projectPath, 'gradle'));
|
||||
|
||||
// If the gradle distribution URL is set, make sure it points to version we want.
|
||||
// If it's not set, do nothing, assuming that we're using a future version of gradle that we don't want to mess with.
|
||||
// For some reason, using ^ and $ don't work. This does the job, though.
|
||||
var distributionUrlRegex = /distributionUrl.*zip/;
|
||||
var distributionUrl = 'distributionUrl=http\\://services.gradle.org/distributions/gradle-2.2.1-all.zip';
|
||||
var gradleWrapperPropertiesPath = path.join(projectPath, 'gradle', 'wrapper', 'gradle-wrapper.properties');
|
||||
shell.sed('-i', distributionUrlRegex, distributionUrl, gradleWrapperPropertiesPath);
|
||||
|
||||
// Update the version of build.gradle in each dependent library.
|
||||
var pluginBuildGradle = path.join(projectPath, 'cordova', 'lib', 'plugin-build.gradle');
|
||||
var subProjects = extractSubProjectPaths();
|
||||
for (var i = 0; i < subProjects.length; ++i) {
|
||||
if (subProjects[i] !== 'CordovaLib') {
|
||||
shell.cp('-f', pluginBuildGradle, path.join(ROOT, subProjects[i], 'build.gradle'));
|
||||
}
|
||||
}
|
||||
|
||||
var subProjectsAsGradlePaths = subProjects.map(function(p) { return ':' + p.replace(/[/\\]/g, ':') });
|
||||
// Write the settings.gradle file.
|
||||
fs.writeFileSync(path.join(projectPath, 'settings.gradle'),
|
||||
'// GENERATED FILE - DO NOT EDIT\n' +
|
||||
'include ":"\n' +
|
||||
'include "' + subProjectsAsGradlePaths.join('"\ninclude "') + '"\n');
|
||||
// Update dependencies within build.gradle.
|
||||
var buildGradle = fs.readFileSync(path.join(projectPath, 'build.gradle'), 'utf8');
|
||||
var depsList = '';
|
||||
subProjectsAsGradlePaths.forEach(function(p) {
|
||||
depsList += ' debugCompile project(path: "' + p + '", configuration: "debug")\n';
|
||||
depsList += ' releaseCompile project(path: "' + p + '", configuration: "release")\n';
|
||||
});
|
||||
buildGradle = buildGradle.replace(/(SUB-PROJECT DEPENDENCIES START)[\s\S]*(\/\/ SUB-PROJECT DEPENDENCIES END)/, '$1\n' + depsList + ' $2');
|
||||
fs.writeFileSync(path.join(projectPath, 'build.gradle'), buildGradle);
|
||||
});
|
||||
},
|
||||
|
||||
/*
|
||||
* Builds the project with gradle.
|
||||
* Returns a promise.
|
||||
*/
|
||||
build: function(build_type, arch, extraArgs) {
|
||||
var builder = this;
|
||||
var wrapper = path.join(ROOT, 'gradlew');
|
||||
var args = this.getArgs(build_type == 'debug' ? 'debug' : 'release', arch, extraArgs);
|
||||
return Q().then(function() {
|
||||
console.log('Running: ' + wrapper + ' ' + args.concat(extraArgs).join(' '));
|
||||
return spawn(wrapper, args);
|
||||
});
|
||||
},
|
||||
|
||||
clean: function(extraArgs) {
|
||||
var builder = this;
|
||||
var wrapper = path.join(ROOT, 'gradlew');
|
||||
var args = builder.getArgs('clean', null, extraArgs);
|
||||
return Q().then(function() {
|
||||
console.log('Running: ' + wrapper + ' ' + args.concat(extraArgs).join(' '));
|
||||
return spawn(wrapper, args);
|
||||
});
|
||||
},
|
||||
|
||||
findOutputApks: function(build_type, arch) {
|
||||
var binDir = path.join(ROOT, 'build', 'outputs', 'apk');
|
||||
return findOutputApksHelper(binDir, build_type, arch);
|
||||
}
|
||||
},
|
||||
|
||||
none: {
|
||||
prepEnv: function() {
|
||||
return Q();
|
||||
},
|
||||
build: function() {
|
||||
console.log('Skipping build...');
|
||||
return Q(null);
|
||||
},
|
||||
clean: function() {
|
||||
return Q();
|
||||
},
|
||||
findOutputApks: function(build_type, arch) {
|
||||
return sortFilesByDate(builders.ant.findOutputApks(build_type, arch).concat(builders.gradle.findOutputApks(build_type, arch)));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function parseOpts(options, resolvedTarget) {
|
||||
// Backwards-compatibility: Allow a single string argument
|
||||
if (typeof options == "string") options = [options];
|
||||
|
||||
var ret = {
|
||||
buildType: 'debug',
|
||||
buildMethod: process.env['ANDROID_BUILD'] || 'ant',
|
||||
arch: null,
|
||||
extraArgs: []
|
||||
};
|
||||
|
||||
var multiValueArgs = {
|
||||
'versionCode': true,
|
||||
'minSdkVersion': true,
|
||||
'gradleArg': true
|
||||
};
|
||||
|
||||
// Iterate through command line options
|
||||
for (var i=0; options && (i < options.length); ++i) {
|
||||
if (/^--/.exec(options[i])) {
|
||||
var keyValue = options[i].substring(2).split('=');
|
||||
var flagName = keyValue.shift();
|
||||
var flagValue = keyValue.join('=');
|
||||
if (multiValueArgs[flagName] && !flagValue) {
|
||||
flagValue = options[i + 1];
|
||||
++i;
|
||||
}
|
||||
switch(flagName) {
|
||||
case 'debug':
|
||||
case 'release':
|
||||
ret.buildType = flagName;
|
||||
break;
|
||||
case 'ant':
|
||||
case 'gradle':
|
||||
ret.buildMethod = flagName;
|
||||
break;
|
||||
case 'device':
|
||||
case 'emulator':
|
||||
// Don't need to do anything special to when building for device vs emulator.
|
||||
// iOS uses this flag to switch on architecture.
|
||||
break;
|
||||
case 'nobuild' :
|
||||
ret.buildMethod = 'none';
|
||||
break;
|
||||
case 'versionCode':
|
||||
ret.extraArgs.push('-PcdvVersionCode=' + flagValue);
|
||||
break;
|
||||
case 'minSdkVersion':
|
||||
ret.extraArgs.push('-PcdvMinSdkVersion=' + flagValue);
|
||||
break;
|
||||
case 'gradleArg':
|
||||
ret.extraArgs.push(flagValue);
|
||||
break;
|
||||
default :
|
||||
console.warn('Build option --\'' + flagName + '\' not recognized (ignoring).');
|
||||
}
|
||||
} else {
|
||||
console.warn('Build option \'' + options[i] + '\' not recognized (ignoring).');
|
||||
}
|
||||
}
|
||||
|
||||
ret.arch = resolvedTarget && resolvedTarget.arch;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Builds the project with the specifed options
|
||||
* Returns a promise.
|
||||
*/
|
||||
module.exports.runClean = function(options) {
|
||||
var opts = parseOpts(options);
|
||||
var builder = builders[opts.buildMethod];
|
||||
return builder.prepEnv()
|
||||
.then(function() {
|
||||
return builder.clean(opts.extraArgs);
|
||||
}).then(function() {
|
||||
shell.rm('-rf', path.join(ROOT, 'out'));
|
||||
});
|
||||
};
|
||||
|
||||
/*
|
||||
* Builds the project with the specifed options
|
||||
* Returns a promise.
|
||||
*/
|
||||
module.exports.run = function(options, optResolvedTarget) {
|
||||
var opts = parseOpts(options, optResolvedTarget);
|
||||
var builder = builders[opts.buildMethod];
|
||||
return builder.prepEnv()
|
||||
.then(function() {
|
||||
return builder.build(opts.buildType, opts.arch, opts.extraArgs);
|
||||
}).then(function() {
|
||||
var apkPaths = builder.findOutputApks(opts.buildType, opts.arch);
|
||||
console.log('Built the following apk(s):');
|
||||
console.log(' ' + apkPaths.join('\n '));
|
||||
return {
|
||||
apkPaths: apkPaths,
|
||||
buildType: opts.buildType,
|
||||
buildMethod: opts.buildMethod
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
/*
|
||||
* Detects the architecture of a device/emulator
|
||||
* Returns "arm" or "x86".
|
||||
*/
|
||||
module.exports.detectArchitecture = function(target) {
|
||||
function helper() {
|
||||
return exec('adb -s ' + target + ' shell cat /proc/cpuinfo', os.tmpdir())
|
||||
.then(function(output) {
|
||||
if (/intel/i.exec(output)) {
|
||||
return 'x86';
|
||||
}
|
||||
return 'arm';
|
||||
});
|
||||
}
|
||||
// It sometimes happens (at least on OS X), that this command will hang forever.
|
||||
// To fix it, either unplug & replug device, or restart adb server.
|
||||
return helper().timeout(1000, 'Device communication timed out. Try unplugging & replugging the device.')
|
||||
.then(null, function(err) {
|
||||
if (/timed out/.exec('' + err)) {
|
||||
// adb kill-server doesn't seem to do the trick.
|
||||
// Could probably find a x-platform version of killall, but I'm not actually
|
||||
// sure that this scenario even happens on non-OSX machines.
|
||||
return exec('killall adb')
|
||||
.then(function() {
|
||||
console.log('adb seems hung. retrying.');
|
||||
return helper()
|
||||
.then(null, function() {
|
||||
// The double kill is sadly often necessary, at least on mac.
|
||||
console.log('Now device not found... restarting adb again.');
|
||||
return exec('killall adb')
|
||||
.then(function() {
|
||||
return helper()
|
||||
.then(null, function() {
|
||||
return Q.reject('USB is flakey. Try unplugging & replugging the device.');
|
||||
});
|
||||
});
|
||||
});
|
||||
}, function() {
|
||||
// For non-killall OS's.
|
||||
return Q.reject(err);
|
||||
})
|
||||
}
|
||||
throw err;
|
||||
});
|
||||
};
|
||||
|
||||
module.exports.findBestApkForArchitecture = function(buildResults, arch) {
|
||||
var paths = buildResults.apkPaths.filter(function(p) {
|
||||
if (buildResults.buildType == 'debug') {
|
||||
return /-debug/.exec(p);
|
||||
}
|
||||
return !/-debug/.exec(p);
|
||||
});
|
||||
var archPattern = new RegExp('-' + arch);
|
||||
var hasArchPattern = /-x86|-arm/;
|
||||
for (var i = 0; i < paths.length; ++i) {
|
||||
if (hasArchPattern.exec(paths[i])) {
|
||||
if (archPattern.exec(paths[i])) {
|
||||
return paths[i];
|
||||
}
|
||||
} else {
|
||||
return paths[i];
|
||||
}
|
||||
}
|
||||
throw new Error('Could not find apk architecture: ' + arch + ' build-type: ' + buildResults.buildType);
|
||||
};
|
||||
|
||||
module.exports.help = function() {
|
||||
console.log('Usage: ' + path.relative(process.cwd(), path.join(ROOT, 'cordova', 'build')) + ' [flags]');
|
||||
console.log('Flags:');
|
||||
console.log(' \'--debug\': will build project in debug mode (default)');
|
||||
console.log(' \'--release\': will build project for release');
|
||||
console.log(' \'--ant\': will build project with ant (default)');
|
||||
console.log(' \'--gradle\': will build project with gradle');
|
||||
console.log(' \'--nobuild\': will skip build process (useful when using run command)');
|
||||
console.log(' \'--versionCode=#\': Override versionCode for this build. Useful for uploading multiple APKs. Requires --gradle.');
|
||||
console.log(' \'--minSdkVersion=#\': Override minSdkVersion for this build. Useful for uploading multiple APKs. Requires --gradle.');
|
||||
console.log(' \'--gradleArg=<gradle command line arg>\': Extra args to pass to the gradle command. Use one flag per arg. Ex. --gradleArg=-PcdvBuildMultipleApks=true');
|
||||
process.exit(0);
|
||||
};
|
||||
612
bin/templates/cordova/lib/cordova.js
vendored
612
bin/templates/cordova/lib/cordova.js
vendored
@@ -1,612 +0,0 @@
|
||||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
var ROOT = WScript.ScriptFullName.split('\\cordova\\lib\\cordova.js').join(''),
|
||||
shell = WScript.CreateObject("WScript.Shell"),
|
||||
fso = WScript.CreateObject('Scripting.FileSystemObject');
|
||||
//device_id for targeting specific device
|
||||
var device_id;
|
||||
//build types
|
||||
var NONE = 0,
|
||||
DEBUG = '--debug',
|
||||
RELEASE = '--release',
|
||||
NO_BUILD = '--nobuild';
|
||||
var build_type = NONE;
|
||||
|
||||
//deploy tpyes
|
||||
var NONE = 0,
|
||||
EMULATOR = 1,
|
||||
DEVICE = 2,
|
||||
TARGET = 3;
|
||||
var deploy_type = NONE;
|
||||
|
||||
|
||||
// log to stdout or stderr
|
||||
function Log(msg, error) {
|
||||
if (error) {
|
||||
WScript.StdErr.WriteLine(msg);
|
||||
}
|
||||
else {
|
||||
WScript.StdOut.WriteLine(msg);
|
||||
}
|
||||
}
|
||||
|
||||
// executes a commmand in the shell, returning stdout
|
||||
function exec(command) {
|
||||
var oExec=shell.Exec(command);
|
||||
var output = new String();
|
||||
while (oExec.Status == 0) {
|
||||
if (!oExec.StdOut.AtEndOfStream) {
|
||||
var line = oExec.StdOut.ReadLine();
|
||||
output += line;
|
||||
}
|
||||
WScript.sleep(100);
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
// executes a command in the shell, returns stdout or stderr if error
|
||||
function exec_out(command) {
|
||||
var oExec=shell.Exec(command);
|
||||
var output = new String();
|
||||
while (oExec.Status == 0) {
|
||||
if (!oExec.StdOut.AtEndOfStream) {
|
||||
var line = oExec.StdOut.ReadLine();
|
||||
// XXX: Change to verbose mode
|
||||
// WScript.StdOut.WriteLine(line);
|
||||
output += line;
|
||||
}
|
||||
WScript.sleep(100);
|
||||
}
|
||||
//Check to make sure our scripts did not encounter an error
|
||||
if (!oExec.StdErr.AtEndOfStream) {
|
||||
var line = oExec.StdErr.ReadAll();
|
||||
return {'error' : true, 'output' : line};
|
||||
}
|
||||
return {'error' : false, 'output' : output};
|
||||
}
|
||||
|
||||
// executes a commmand in the shell and outputs stdout and fails on stderr
|
||||
function exec_verbose(command) {
|
||||
//Log("Command: " + command);
|
||||
var oShell=shell.Exec(command);
|
||||
while (oShell.Status == 0) {
|
||||
//Wait a little bit so we're not super looping
|
||||
WScript.sleep(100);
|
||||
//Print any stdout output from the script
|
||||
if (!oShell.StdOut.AtEndOfStream) {
|
||||
var line = oShell.StdOut.ReadLine();
|
||||
Log(line);
|
||||
}
|
||||
}
|
||||
//Check to make sure our scripts did not encounter an error
|
||||
if (!oShell.StdErr.AtEndOfStream) {
|
||||
var line = oShell.StdErr.ReadAll();
|
||||
Log(line, true);
|
||||
WScript.Quit(2);
|
||||
}
|
||||
}
|
||||
|
||||
function version(path) {
|
||||
var cordovajs_path = path + "\\assets\\www\\cordova.js";
|
||||
if(fso.FileExists(cordovajs_path)) {
|
||||
var f = fso.OpenTextFile(cordovajs_path, 1,2);
|
||||
var cordovajs = f.ReadAll();
|
||||
f.Close();
|
||||
var version_regex = /^.*CORDOVA_JS_BUILD_LABEL.*$/m;
|
||||
var version_line = cordovajs.match(version_regex) + "";
|
||||
var version = version_line.match(/(\d+)\.(\d+)\.(\d+)(rc\d)?/) + "";
|
||||
// TODO : figure out why this isn't matching properly so we can remove this substring workaround.
|
||||
Log(version.substr(0, ((version.length/2) -1)));
|
||||
} else {
|
||||
Log("Error : Could not find cordova js.", true);
|
||||
Log("Expected Location : " + cordovajs_path, true);
|
||||
WScript.Quit(2);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function get_devices() {
|
||||
var device_list = []
|
||||
var local_devices = shell.Exec("%comspec% /c adb devices").StdOut.ReadAll();
|
||||
if (local_devices.match(/\w+\tdevice/)) {
|
||||
devices = local_devices.split('\r\n');
|
||||
//format (ID DESCRIPTION)
|
||||
for (i in devices) {
|
||||
if (devices[i].match(/\w+\tdevice/) && !devices[i].match(/emulator/)) {
|
||||
device_list.push(devices[i].replace(/\t/, ' '));
|
||||
}
|
||||
}
|
||||
}
|
||||
return device_list
|
||||
}
|
||||
|
||||
function list_devices() {
|
||||
var devices = get_devices();
|
||||
if (devices.length > 0) {
|
||||
for (i in devices) {
|
||||
Log(devices[i]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
Log('No devices found, if your device is connected and not showing,');
|
||||
Log(' then try and install the drivers for your device.');
|
||||
Log(' http://developer.android.com/tools/extras/oem-usb.html');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function get_emulator_images() {
|
||||
var avd_list = [];
|
||||
var local_emulators = shell.Exec("%comspec% /c android list avds").StdOut.ReadAll();
|
||||
if (local_emulators.match(/Name\:/)) {
|
||||
emulators = local_emulators.split('\n');
|
||||
var count = 0;
|
||||
var output = '';
|
||||
for (i in emulators) {
|
||||
// Find the line with the emulator name.
|
||||
if (emulators[i].match(/Name\:/)) {
|
||||
// strip description
|
||||
var emulator_name = emulators[i].replace(/\s*Name\:\s/, '') + ' ';
|
||||
avd_list.push(emulator_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
return avd_list;
|
||||
}
|
||||
|
||||
function list_emulator_images() {
|
||||
var images = get_emulator_images();
|
||||
if (images.length > 0) {
|
||||
for(i in images) {
|
||||
Log(images[i]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
Log('No emulators found, if you would like to create an emulator follow the instructions');
|
||||
Log(' provided here : http://developer.android.com/tools/devices/index.html');
|
||||
Log(' Or run \'android create avd --name <name> --target <targetID>\' in on the command line.');
|
||||
}
|
||||
}
|
||||
|
||||
function get_started_emulators() {
|
||||
var started_emulators = [];
|
||||
var local_devices = shell.Exec("%comspec% /c adb devices").StdOut.ReadAll();
|
||||
if (local_devices.match(/emulator/)) {
|
||||
devices = local_devices.split('\r\n');
|
||||
//format (ID DESCRIPTION)
|
||||
for (i in devices) {
|
||||
if (devices[i].match(/\w+\tdevice/) && devices[i].match(/emulator/)) {
|
||||
started_emulators.push(devices[i].replace(/\t/, ' '));
|
||||
}
|
||||
}
|
||||
}
|
||||
return started_emulators
|
||||
}
|
||||
|
||||
function list_started_emulators() {
|
||||
var images = get_started_emulators();
|
||||
if (images.length > 0) {
|
||||
for(i in images) {
|
||||
Log(images[i]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
Log('No started emulators found, if you would like to start an emulator call ');
|
||||
Log('\'list-emulator-images\'');
|
||||
Log(' to get the name of an emulator and then start the emulator with');
|
||||
Log('\'start-emulator <Name>\'');
|
||||
}
|
||||
}
|
||||
|
||||
function create_emulator() {
|
||||
//get targets
|
||||
var targets = shell.Exec('android.bat list targets').StdOut.ReadAll().match(/id:\s\d+/g);
|
||||
if(targets) {
|
||||
exec('%comspec% /c android create avd --name cordova_emulator --target ' + targets[targets.length - 1].replace(/id: /, ""));
|
||||
} else {
|
||||
Log("You do not have any android targets setup. Please create at least one target with the `android` command so that an emulator can be created.", true);
|
||||
WScript.Quit(69);
|
||||
}
|
||||
}
|
||||
|
||||
function start_emulator(name) {
|
||||
var emulators = get_emulator_images();
|
||||
var started_emulators = get_started_emulators();
|
||||
var num_started = started_emulators.length;
|
||||
var emulator_name;
|
||||
var started = false;
|
||||
if (name) {
|
||||
for (i in emulators) {
|
||||
if (emulators[i].substr(0,name.length) == name) {
|
||||
Log("Starting emulator : " + name);
|
||||
shell.Exec("%comspec% /c emulator -avd " + name + " &");
|
||||
//shell.Run("%comspec% /c start cmd /c emulator -cpu-delay 0 -no-boot-anim -cache %Temp%\cache -avd " + name);
|
||||
started = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (emulators.length > 0 && started_emulators.length == 0) {
|
||||
emulator_name = emulators[0].split(' ', 1)[0];
|
||||
start_emulator(emulator_name);
|
||||
return;
|
||||
} else if (started_emulators.length > 0) {
|
||||
Log("Emulator already started : " + started_emulators[0].split(' ', 1));
|
||||
return;
|
||||
} else {
|
||||
Log("Error : unable to start emulator, ensure you have emulators availible by checking \'list-emulator-images\'", true);
|
||||
WScript.Quit(2);
|
||||
}
|
||||
}
|
||||
if (!started) {
|
||||
Log("Error : unable to start emulator, ensure you have emulators availible by checking \'list-emulator-images\'", true);
|
||||
WScript.Quit(2);
|
||||
}
|
||||
else {
|
||||
// wait for emulator to get the ID
|
||||
Log('Waiting for emulator...');
|
||||
var boot_anim = null;
|
||||
var emulator_ID = null;
|
||||
var new_started = null;
|
||||
var i = 0;
|
||||
while(emulator_ID == null && i < 10) {
|
||||
new_started = get_started_emulators();
|
||||
if(new_started.length > started_emulators.length) {
|
||||
// find new emulator that was just started to get it's ID
|
||||
for(var i = 0; i < new_started.length; i++) {
|
||||
if (new_started[i] != started_emulators[i]) {
|
||||
emulator_ID = new_started[i].split(' ', 1)[0];
|
||||
boot_anim = exec_out('%comspec% /c adb -s ' + emulator_ID + ' shell getprop init.svc.bootanim');
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (i == 10) {
|
||||
Log('\nEmulator start timed out.');
|
||||
WScript.Quit(2);
|
||||
}
|
||||
i = 0;
|
||||
WScript.Stdout.Write('Booting up emulator (this may take a while).');
|
||||
// use boot animation property to tell when boot is complete.
|
||||
while (!boot_anim.output.match(/stopped/) && i < 100) {
|
||||
boot_anim = exec_out('%comspec% /c adb -s ' + emulator_ID + ' shell getprop init.svc.bootanim');
|
||||
i++;
|
||||
WScript.Stdout.Write('.');
|
||||
WScript.Sleep(2000);
|
||||
}
|
||||
|
||||
if (i < 100) {
|
||||
Log('\nBoot Complete!');
|
||||
// Unlock the device
|
||||
shell.Exec("%comspec% /c adb -s " + emulator_ID + " shell input keyevent 82");
|
||||
} else {
|
||||
Log('\nEmulator boot timed out. Failed to load emulator');
|
||||
WScript.Quit(2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function get_apk(path) {
|
||||
// check if file .apk has been created
|
||||
if (fso.FolderExists(path + '\\bin')) {
|
||||
var path_to_apk;
|
||||
var out_folder = fso.GetFolder(path + '\\bin');
|
||||
var out_files = new Enumerator(out_folder.Files);
|
||||
for (;!out_files.atEnd(); out_files.moveNext()) {
|
||||
var path = out_files.item() + '';
|
||||
if (fso.GetExtensionName(path) == 'apk' && !path.match(/unaligned/)) {
|
||||
path_to_apk = out_files.item();
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (path_to_apk) {
|
||||
return path_to_apk;
|
||||
}
|
||||
else {
|
||||
Log('Failed to find apk, make sure you project is built and there is an ', true);
|
||||
Log(' apk in <project>\\bin\\. To build your project use \'<project>\\cordova\\build\'', true);
|
||||
WScript.Quit(2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function install_device(path) {
|
||||
var devices = get_devices();
|
||||
var use_target = false;
|
||||
if (devices.length < 1) {
|
||||
Log("Error : No devices found to install to, make sure there are devices", true);
|
||||
Log(" availible by checking \'<project_dir>\\cordova\\lib\\list-devices\'", true);
|
||||
WScript.Quit(2);
|
||||
}
|
||||
launch(path, devices[0].split(' ', 1)[0], true);
|
||||
}
|
||||
|
||||
function install_emulator(path) {
|
||||
var emulators = get_started_emulators();
|
||||
var use_target = false;
|
||||
if (emulators.length < 1) {
|
||||
Log("Error : No emulators found to install to, make sure there are emulators", true);
|
||||
Log(" availible by checking \'<project_dir>\\cordova\\lib\\list-started-emulators\'", true);
|
||||
WScript.Quit(2);
|
||||
}
|
||||
launch(path, emulators[0].split(' ', 1)[0], false);
|
||||
}
|
||||
|
||||
function install_target(path) {
|
||||
if(device_id) {
|
||||
var device = false;
|
||||
var emulators = get_started_emulators();
|
||||
var devices = get_devices();
|
||||
var exists = false;
|
||||
for (i in emulators) {
|
||||
if (emulators[i].substr(0,device_id.length) == device_id) {
|
||||
exists = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (i in devices) {
|
||||
if (devices[i].substr(0,device_id.length) == device_id) {
|
||||
exists = true;
|
||||
device = true
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!exists) {
|
||||
Log("Error : Unable to find target " + device_id, true);
|
||||
Log("Please ensure the target exists by checking \'<project>\\cordova\\lib\\list-started-emulators'");
|
||||
Log(" Or \'<project>\\cordova\\lib\\list-devices'");
|
||||
}
|
||||
launch(path, device_id, device);
|
||||
}
|
||||
else {
|
||||
Log("You cannot install to a target without providing a valid target ID.", true);
|
||||
WScript.Quit(2);
|
||||
}
|
||||
}
|
||||
|
||||
function launch(path, id, device) {
|
||||
if(id) {
|
||||
var path_to_apk = get_apk(path);
|
||||
if (path_to_apk) {
|
||||
var launch_name = exec_out("%comspec% /c java -jar "+path+"\\cordova\\appinfo.jar "+path+"\\AndroidManifest.xml");
|
||||
if (launch_name.error) {
|
||||
Log("Failed to get application name from appinfo.jar + AndroidManifest : ", true);
|
||||
Log("Output : " + launch_name.output, true);
|
||||
WScript.Quit(2);
|
||||
}
|
||||
if (device) {
|
||||
// install on device (-d)
|
||||
Log("Installing app on device...");
|
||||
} else {
|
||||
// install on emulator (-e)
|
||||
Log("Installing app on emulator...");
|
||||
}
|
||||
var cmd = '%comspec% /c adb -s ' + id + ' install -r ' + path_to_apk;
|
||||
var install = exec_out(cmd);
|
||||
if ( install.error && install.output.match(/Failure/)) {
|
||||
Log("Error : Could not install apk to emulator : ", true);
|
||||
Log(install.output, true);
|
||||
WScript.Quit(2);
|
||||
}
|
||||
else {
|
||||
Log(install.output);
|
||||
}
|
||||
// launch the application
|
||||
Log("Launching application...");
|
||||
cmd = '%comspec% /c adb -s ' + id + ' shell am start -W -a android.intent.action.MAIN -n ' + launch_name.output;
|
||||
exec_verbose(cmd);
|
||||
}
|
||||
else {
|
||||
Log('Failed to find apk, make sure you project is built and there is an ', true);
|
||||
Log(' apk in <project>\\bin\\. To build your project use \'<project>\\cordova\\build\'', true);
|
||||
WScript.Quit(2);
|
||||
}
|
||||
}
|
||||
else {
|
||||
Log("You cannot install to a target without providing a valid target ID.", true);
|
||||
WScript.Quit(2);
|
||||
}
|
||||
}
|
||||
|
||||
function clean(path) {
|
||||
Log("Cleaning project...");
|
||||
exec("%comspec% /c ant.bat clean -f "+path+"\\build.xml 2>&1");
|
||||
}
|
||||
|
||||
function log() {
|
||||
// filter out nativeGetEnabledTags spam from latest sdk bug.
|
||||
shell.Run("%comspec% /c adb logcat | grep -v nativeGetEnabledTags");
|
||||
}
|
||||
|
||||
function build(path) {
|
||||
switch (build_type) {
|
||||
case DEBUG :
|
||||
clean(path);
|
||||
Log("Building project...");
|
||||
exec_verbose("%comspec% /c ant.bat debug -f "+path+"\\build.xml 2>&1");
|
||||
break;
|
||||
case RELEASE :
|
||||
clean(path);
|
||||
Log("Building project...");
|
||||
exec_verbose("%comspec% /c ant.bat release -f "+path+"\\build.xml 2>&1");
|
||||
break;
|
||||
case NO_BUILD :
|
||||
Log("Skipping build process.");
|
||||
break;
|
||||
case NONE :
|
||||
clean(path);
|
||||
Log("WARNING: [ --debug | --release | --nobuild ] not specified, defaulting to --debug.");
|
||||
exec_verbose("%comspec% /c ant.bat debug -f "+path+"\\build.xml 2>&1");
|
||||
break;
|
||||
default :
|
||||
Log("Build option not recognized: " + build_type, true);
|
||||
WScript.Quit(2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function run(path) {
|
||||
switch(deploy_type) {
|
||||
case EMULATOR :
|
||||
build(path);
|
||||
if(get_started_emulators().length == 0) {
|
||||
start_emulator();
|
||||
}
|
||||
//TODO : Start emulator if one isn't started, and create one if none exists.
|
||||
install_emulator(path);
|
||||
break;
|
||||
case DEVICE :
|
||||
build(path);
|
||||
install_device(path);
|
||||
break;
|
||||
case TARGET :
|
||||
build(path);
|
||||
install_target(path);
|
||||
break;
|
||||
case NONE :
|
||||
if (get_devices().length > 0) {
|
||||
Log("WARNING: [ --target=<ID> | --emulator | --device ] not specified, defaulting to --device");
|
||||
deploy_type = DEVICE;
|
||||
} else {
|
||||
Log("WARNING: [ --target=<ID> | --emulator | --device ] not specified, defaulting to --emulator");
|
||||
deploy_type = EMULATOR;
|
||||
}
|
||||
run(path);
|
||||
break;
|
||||
default :
|
||||
Log("Deploy option not recognized: " + deploy_type, true);
|
||||
WScript.Quit(2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var args = WScript.Arguments;
|
||||
if (args.count() == 0) {
|
||||
Log("Error: no args provided.");
|
||||
WScript.Quit(2);
|
||||
}
|
||||
else {
|
||||
// parse command
|
||||
switch(args(0)) {
|
||||
case "version" :
|
||||
version(ROOT);
|
||||
break;
|
||||
case "build" :
|
||||
if(args.Count() > 1) {
|
||||
if (args(1) == "--release") {
|
||||
build_type = RELEASE;
|
||||
}
|
||||
else if (args(1) == "--debug") {
|
||||
build_type = DEBUG;
|
||||
}
|
||||
else if (args(1) == "--nobuild") {
|
||||
build_type = NO_BUILD;
|
||||
}
|
||||
else {
|
||||
Log('Error: \"' + args(i) + '\" is not recognized as a build option', true);
|
||||
WScript.Quit(2);
|
||||
}
|
||||
}
|
||||
build(ROOT);
|
||||
break;
|
||||
case "clean" :
|
||||
clean();
|
||||
break;
|
||||
case "log" :
|
||||
log();
|
||||
break;
|
||||
case "list-devices" :
|
||||
list_devices();
|
||||
break;
|
||||
case "list-emulator-images" :
|
||||
list_emulator_images();
|
||||
break;
|
||||
case "list-started-emulators" :
|
||||
list_started_emulators();
|
||||
break;
|
||||
case "start-emulator" :
|
||||
if (args.Count() > 1) {
|
||||
start_emulator(args(1))
|
||||
} else {
|
||||
start_emulator();
|
||||
}
|
||||
break;
|
||||
case "install-emulator" :
|
||||
if (args.Count() == 2) {
|
||||
if (args(1).substr(0,9) == "--target=") {
|
||||
device_id = args(1).split('--target=').join('');
|
||||
install_emulator(ROOT);
|
||||
} else {
|
||||
Log('Error: \"' + args(1) + '\" is not recognized as an install option', true);
|
||||
WScript.Quit(2);
|
||||
}
|
||||
} else {
|
||||
install_emulator(ROOT);
|
||||
}
|
||||
break;
|
||||
case "install-device" :
|
||||
if (args.Count() == 2) {
|
||||
if (args(1).substr(0,9) == "--target=") {
|
||||
device_id = args(1).split('--target=').join('');
|
||||
install_target(ROOT);
|
||||
} else {
|
||||
Log('Error: \"' + args(1) + '\" is not recognized as an install option', true);
|
||||
WScript.Quit(2);
|
||||
}
|
||||
} else {
|
||||
install_device(ROOT);
|
||||
}
|
||||
break;
|
||||
case "run" :
|
||||
//parse args
|
||||
for(var i = 1; i < args.Count(); i++) {
|
||||
if (args(i) == "--release") {
|
||||
build_type = RELEASE;
|
||||
}
|
||||
else if (args(i) == "--debug") {
|
||||
build_type = DEBUG;
|
||||
}
|
||||
else if (args(i) == "--nobuild") {
|
||||
build_type = NO_BUILD;
|
||||
}
|
||||
else if (args(i) == "--emulator" || args(i) == "-e") {
|
||||
deploy_type = EMULATOR;
|
||||
}
|
||||
else if (args(i) == "--device" || args(i) == "-d") {
|
||||
deploy_type = DEVICE;
|
||||
}
|
||||
else if (args(i).substr(0,9) == "--target=") {
|
||||
device_id = args(i).split("--target=").join("");
|
||||
deploy_type = TARGET;
|
||||
}
|
||||
else {
|
||||
Log('Error: \"' + args(i) + '\" is not recognized as a run option', true);
|
||||
WScript.Quit(2);
|
||||
}
|
||||
}
|
||||
run(ROOT);
|
||||
break;
|
||||
default :
|
||||
Log("Cordova does not regognize the command " + args(0), true);
|
||||
WScript.Quit(2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
123
bin/templates/cordova/lib/device.js
vendored
Normal file
123
bin/templates/cordova/lib/device.js
vendored
Normal file
@@ -0,0 +1,123 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
|
||||
var exec = require('./exec'),
|
||||
Q = require('q'),
|
||||
path = require('path'),
|
||||
os = require('os'),
|
||||
build = require('./build'),
|
||||
appinfo = require('./appinfo'),
|
||||
ROOT = path.join(__dirname, '..', '..');
|
||||
|
||||
/**
|
||||
* Returns a promise for the list of the device ID's found
|
||||
* @param lookHarder When true, try restarting adb if no devices are found.
|
||||
*/
|
||||
module.exports.list = function(lookHarder) {
|
||||
function helper() {
|
||||
return exec('adb devices', os.tmpdir())
|
||||
.then(function(output) {
|
||||
var response = output.split('\n');
|
||||
var device_list = [];
|
||||
for (var i = 1; i < response.length; i++) {
|
||||
if (response[i].match(/\w+\tdevice/) && !response[i].match(/emulator/)) {
|
||||
device_list.push(response[i].replace(/\tdevice/, '').replace('\r', ''));
|
||||
}
|
||||
}
|
||||
return device_list;
|
||||
});
|
||||
}
|
||||
return helper()
|
||||
.then(function(list) {
|
||||
if (list.length === 0 && lookHarder) {
|
||||
// adb kill-server doesn't seem to do the trick.
|
||||
// Could probably find a x-platform version of killall, but I'm not actually
|
||||
// sure that this scenario even happens on non-OSX machines.
|
||||
return exec('killall adb')
|
||||
.then(function() {
|
||||
console.log('Restarting adb to see if more devices are detected.');
|
||||
return helper();
|
||||
}, function() {
|
||||
// For non-killall OS's.
|
||||
return list;
|
||||
});
|
||||
}
|
||||
return list;
|
||||
});
|
||||
}
|
||||
|
||||
module.exports.resolveTarget = function(target) {
|
||||
return this.list(true)
|
||||
.then(function(device_list) {
|
||||
if (!device_list || !device_list.length) {
|
||||
return Q.reject('ERROR: Failed to deploy to device, no devices found.');
|
||||
}
|
||||
// default device
|
||||
target = target || device_list[0];
|
||||
|
||||
if (device_list.indexOf(target) < 0) {
|
||||
return Q.reject('ERROR: Unable to find target \'' + target + '\'.');
|
||||
}
|
||||
|
||||
return build.detectArchitecture(target)
|
||||
.then(function(arch) {
|
||||
return { target: target, arch: arch, isEmulator: false };
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/*
|
||||
* Installs a previously built application on the device
|
||||
* and launches it.
|
||||
* Returns a promise.
|
||||
*/
|
||||
module.exports.install = function(target, buildResults) {
|
||||
return Q().then(function() {
|
||||
if (target && typeof target == 'object') {
|
||||
return target;
|
||||
}
|
||||
return module.exports.resolveTarget(target);
|
||||
}).then(function(resolvedTarget) {
|
||||
var apk_path = build.findBestApkForArchitecture(buildResults, resolvedTarget.arch);
|
||||
var launchName = appinfo.getActivityName();
|
||||
console.log('Using apk: ' + apk_path);
|
||||
console.log('Installing app on device...');
|
||||
var cmd = 'adb -s ' + resolvedTarget.target + ' install -r "' + apk_path + '"';
|
||||
return exec(cmd, os.tmpdir())
|
||||
.then(function(output) {
|
||||
if (output.match(/Failure/)) return Q.reject('ERROR: Failed to install apk to device: ' + output);
|
||||
|
||||
//unlock screen
|
||||
var cmd = 'adb -s ' + resolvedTarget.target + ' shell input keyevent 82';
|
||||
return exec(cmd, os.tmpdir());
|
||||
}, function(err) { return Q.reject('ERROR: Failed to install apk to device: ' + err); })
|
||||
.then(function() {
|
||||
// launch the application
|
||||
console.log('Launching application...');
|
||||
var cmd = 'adb -s ' + resolvedTarget.target + ' shell am start -W -a android.intent.action.MAIN -n ' + launchName;
|
||||
return exec(cmd, os.tmpdir());
|
||||
}).then(function() {
|
||||
console.log('LAUNCH SUCCESS');
|
||||
}, function(err) {
|
||||
return Q.reject('ERROR: Failed to launch application on device: ' + err);
|
||||
});
|
||||
});
|
||||
}
|
||||
336
bin/templates/cordova/lib/emulator.js
vendored
Normal file
336
bin/templates/cordova/lib/emulator.js
vendored
Normal file
@@ -0,0 +1,336 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
|
||||
var shell = require('shelljs'),
|
||||
exec = require('./exec'),
|
||||
Q = require('q'),
|
||||
path = require('path'),
|
||||
os = require('os'),
|
||||
appinfo = require('./appinfo'),
|
||||
build = require('./build'),
|
||||
ROOT = path.join(__dirname, '..', '..'),
|
||||
child_process = require('child_process'),
|
||||
new_emulator = 'cordova_emulator';
|
||||
var check_reqs = require('./check_reqs');
|
||||
|
||||
/**
|
||||
* Returns a Promise for a list of emulator images in the form of objects
|
||||
* {
|
||||
name : <emulator_name>,
|
||||
path : <path_to_emulator_image>,
|
||||
target : <api_target>,
|
||||
abi : <cpu>,
|
||||
skin : <skin>
|
||||
}
|
||||
*/
|
||||
module.exports.list_images = function() {
|
||||
return exec('android list avds')
|
||||
.then(function(output) {
|
||||
var response = output.split('\n');
|
||||
var emulator_list = [];
|
||||
for (var i = 1; i < response.length; i++) {
|
||||
// To return more detailed information use img_obj
|
||||
var img_obj = {};
|
||||
if (response[i].match(/Name:\s/)) {
|
||||
img_obj['name'] = response[i].split('Name: ')[1].replace('\r', '');
|
||||
if (response[i + 1].match(/Path:\s/)) {
|
||||
i++;
|
||||
img_obj['path'] = response[i].split('Path: ')[1].replace('\r', '');
|
||||
}
|
||||
if (response[i + 1].match(/\(API\slevel\s/)) {
|
||||
i++;
|
||||
img_obj['target'] = response[i].replace('\r', '');
|
||||
}
|
||||
if (response[i + 1].match(/ABI:\s/)) {
|
||||
i++;
|
||||
img_obj['abi'] = response[i].split('ABI: ')[1].replace('\r', '');
|
||||
}
|
||||
if (response[i + 1].match(/Skin:\s/)) {
|
||||
i++;
|
||||
img_obj['skin'] = response[i].split('Skin: ')[1].replace('\r', '');
|
||||
}
|
||||
|
||||
emulator_list.push(img_obj);
|
||||
}
|
||||
/* To just return a list of names use this
|
||||
if (response[i].match(/Name:\s/)) {
|
||||
emulator_list.push(response[i].split('Name: ')[1].replace('\r', '');
|
||||
}*/
|
||||
|
||||
}
|
||||
return emulator_list;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Will return the closest avd to the projects target
|
||||
* or undefined if no avds exist.
|
||||
* Returns a promise.
|
||||
*/
|
||||
module.exports.best_image = function() {
|
||||
var project_target = check_reqs.get_target().replace('android-', '');
|
||||
return this.list_images()
|
||||
.then(function(images) {
|
||||
var closest = 9999;
|
||||
var best = images[0];
|
||||
for (i in images) {
|
||||
var target = images[i].target;
|
||||
if(target) {
|
||||
var num = target.split('(API level ')[1].replace(')', '');
|
||||
if (num == project_target) {
|
||||
return images[i];
|
||||
} else if (project_target - num < closest && project_target > num) {
|
||||
var closest = project_target - num;
|
||||
best = images[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
return best;
|
||||
});
|
||||
}
|
||||
|
||||
// Returns a promise.
|
||||
module.exports.list_started = function() {
|
||||
return exec('adb devices', os.tmpdir())
|
||||
.then(function(output) {
|
||||
var response = output.split('\n');
|
||||
var started_emulator_list = [];
|
||||
for (var i = 1; i < response.length; i++) {
|
||||
if (response[i].match(/device/) && response[i].match(/emulator/)) {
|
||||
started_emulator_list.push(response[i].replace(/\tdevice/, '').replace('\r', ''));
|
||||
}
|
||||
}
|
||||
return started_emulator_list;
|
||||
});
|
||||
}
|
||||
|
||||
// Returns a promise.
|
||||
module.exports.list_targets = function() {
|
||||
return exec('android list targets', os.tmpdir())
|
||||
.then(function(output) {
|
||||
var target_out = output.split('\n');
|
||||
var targets = [];
|
||||
for (var i = target_out.length; i >= 0; i--) {
|
||||
if(target_out[i].match(/id:/)) {
|
||||
targets.push(targets[i].split(' ')[1]);
|
||||
}
|
||||
}
|
||||
return targets;
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
* Starts an emulator with the given ID,
|
||||
* and returns the started ID of that emulator.
|
||||
* If no ID is given it will used the first image available,
|
||||
* if no image is available it will error out (maybe create one?).
|
||||
*
|
||||
* Returns a promise.
|
||||
*/
|
||||
module.exports.start = function(emulator_ID) {
|
||||
var self = this;
|
||||
var emulator_id, num_started, started_emulators;
|
||||
|
||||
return self.list_started()
|
||||
.then(function(list) {
|
||||
started_emulators = list;
|
||||
num_started = started_emulators.length;
|
||||
if (!emulator_ID) {
|
||||
return self.list_images()
|
||||
.then(function(emulator_list) {
|
||||
if (emulator_list.length > 0) {
|
||||
return self.best_image()
|
||||
.then(function(best) {
|
||||
emulator_ID = best.name;
|
||||
console.log('WARNING : no emulator specified, defaulting to ' + emulator_ID);
|
||||
return emulator_ID;
|
||||
});
|
||||
} else {
|
||||
var androidCmd = check_reqs.getAbsoluteAndroidCmd();
|
||||
return Q.reject('ERROR : No emulator images (avds) found.\n' +
|
||||
'1. Download desired System Image by running: ' + androidCmd + ' sdk\n' +
|
||||
'2. Create an AVD by running: ' + androidCmd + ' avd\n' +
|
||||
'HINT: For a faster emulator, use an Intel System Image and install the HAXM device driver\n');
|
||||
}
|
||||
});
|
||||
} else {
|
||||
return Q(emulator_ID);
|
||||
}
|
||||
}).then(function() {
|
||||
var cmd = 'emulator';
|
||||
var args = ['-avd', emulator_ID];
|
||||
var proc = child_process.spawn(cmd, args, { stdio: 'inherit', detached: true });
|
||||
proc.unref(); // Don't wait for it to finish, since the emulator will probably keep running for a long time.
|
||||
}).then(function() {
|
||||
// wait for emulator to start
|
||||
console.log('Waiting for emulator...');
|
||||
return self.wait_for_emulator(num_started);
|
||||
}).then(function(new_started) {
|
||||
if (new_started.length > 1) {
|
||||
for (i in new_started) {
|
||||
if (started_emulators.indexOf(new_started[i]) < 0) {
|
||||
emulator_id = new_started[i];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
emulator_id = new_started[0];
|
||||
}
|
||||
if (!emulator_id) return Q.reject('ERROR : Failed to start emulator, could not find new emulator');
|
||||
|
||||
//wait for emulator to boot up
|
||||
process.stdout.write('Booting up emulator (this may take a while)...');
|
||||
return self.wait_for_boot(emulator_id);
|
||||
}).then(function() {
|
||||
console.log('BOOT COMPLETE');
|
||||
|
||||
//unlock screen
|
||||
return exec('adb -s ' + emulator_id + ' shell input keyevent 82', os.tmpdir());
|
||||
}).then(function() {
|
||||
//return the new emulator id for the started emulators
|
||||
return emulator_id;
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
* Waits for the new emulator to apear on the started-emulator list.
|
||||
* Returns a promise with a list of newly started emulators' IDs.
|
||||
*/
|
||||
module.exports.wait_for_emulator = function(num_running) {
|
||||
var self = this;
|
||||
return self.list_started()
|
||||
.then(function(new_started) {
|
||||
if (new_started.length > num_running) {
|
||||
return new_started;
|
||||
} else {
|
||||
return Q.delay(1000).then(function() {
|
||||
return self.wait_for_emulator(num_running);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
* Waits for the boot animation property of the emulator to switch to 'stopped'
|
||||
*/
|
||||
module.exports.wait_for_boot = function(emulator_id) {
|
||||
var self = this;
|
||||
return exec('adb -s ' + emulator_id + ' shell getprop init.svc.bootanim', os.tmpdir())
|
||||
.then(function(output) {
|
||||
if (output.match(/stopped/)) {
|
||||
return;
|
||||
} else {
|
||||
process.stdout.write('.');
|
||||
return Q.delay(3000).then(function() {
|
||||
return self.wait_for_boot(emulator_id);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
* Create avd
|
||||
* TODO : Enter the stdin input required to complete the creation of an avd.
|
||||
* Returns a promise.
|
||||
*/
|
||||
module.exports.create_image = function(name, target) {
|
||||
console.log('Creating avd named ' + name);
|
||||
if (target) {
|
||||
return exec('android create avd --name ' + name + ' --target ' + target)
|
||||
.then(null, function(error) {
|
||||
console.error('ERROR : Failed to create emulator image : ');
|
||||
console.error(' Do you have the latest android targets including ' + target + '?');
|
||||
console.error(create.output);
|
||||
});
|
||||
} else {
|
||||
console.log('WARNING : Project target not found, creating avd with a different target but the project may fail to install.');
|
||||
return exec('android create avd --name ' + name + ' --target ' + this.list_targets()[0])
|
||||
.then(function() {
|
||||
// TODO: This seems like another error case, even though it always happens.
|
||||
console.error('ERROR : Unable to create an avd emulator, no targets found.');
|
||||
console.error('Please insure you have targets available by running the "android" command');
|
||||
return Q.reject();
|
||||
}, function(error) {
|
||||
console.error('ERROR : Failed to create emulator image : ');
|
||||
console.error(error);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
module.exports.resolveTarget = function(target) {
|
||||
return this.list_started()
|
||||
.then(function(emulator_list) {
|
||||
if (emulator_list.length < 1) {
|
||||
return Q.reject('No started emulators found, please start an emultor before deploying your project.');
|
||||
}
|
||||
|
||||
// default emulator
|
||||
target = target || emulator_list[0];
|
||||
if (emulator_list.indexOf(target) < 0) {
|
||||
return Q.reject('Unable to find target \'' + target + '\'. Failed to deploy to emulator.');
|
||||
}
|
||||
|
||||
return build.detectArchitecture(target)
|
||||
.then(function(arch) {
|
||||
return {target:target, arch:arch, isEmulator:true};
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/*
|
||||
* Installs a previously built application on the emulator and launches it.
|
||||
* If no target is specified, then it picks one.
|
||||
* If no started emulators are found, error out.
|
||||
* Returns a promise.
|
||||
*/
|
||||
module.exports.install = function(target, buildResults) {
|
||||
return Q().then(function() {
|
||||
if (target && typeof target == 'object') {
|
||||
return target;
|
||||
}
|
||||
return module.exports.resolveTarget(target);
|
||||
}).then(function(resolvedTarget) {
|
||||
var apk_path = build.findBestApkForArchitecture(buildResults, resolvedTarget.arch);
|
||||
console.log('Installing app on emulator...');
|
||||
console.log('Using apk: ' + apk_path);
|
||||
return exec('adb -s ' + resolvedTarget.target + ' install -r "' + apk_path + '"', os.tmpdir())
|
||||
.then(function(output) {
|
||||
if (output.match(/Failure/)) {
|
||||
return Q.reject('Failed to install apk to emulator: ' + output);
|
||||
}
|
||||
return Q();
|
||||
}, function(err) {
|
||||
return Q.reject('Failed to install apk to emulator: ' + err);
|
||||
}).then(function() {
|
||||
//unlock screen
|
||||
return exec('adb -s ' + resolvedTarget.target + ' shell input keyevent 82', os.tmpdir());
|
||||
}).then(function() {
|
||||
// launch the application
|
||||
console.log('Launching application...');
|
||||
var launchName = appinfo.getActivityName();
|
||||
cmd = 'adb -s ' + resolvedTarget.target + ' shell am start -W -a android.intent.action.MAIN -n ' + launchName;
|
||||
return exec(cmd, os.tmpdir());
|
||||
}).then(function(output) {
|
||||
console.log('LAUNCH SUCCESS');
|
||||
}, function(err) {
|
||||
return Q.reject('Failed to launch app on emulator: ' + err);
|
||||
});
|
||||
});
|
||||
}
|
||||
41
bin/templates/cordova/lib/exec.js
vendored
Normal file
41
bin/templates/cordova/lib/exec.js
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
|
||||
var child_process = require('child_process'),
|
||||
Q = require('q');
|
||||
|
||||
// Takes a command and optional current working directory.
|
||||
// Returns a promise that either resolves with the stdout, or
|
||||
// rejects with an error message and the stderr.
|
||||
module.exports = function(cmd, opt_cwd) {
|
||||
var d = Q.defer();
|
||||
try {
|
||||
child_process.exec(cmd, {cwd: opt_cwd, maxBuffer: 1024000}, function(err, stdout, stderr) {
|
||||
if (err) d.reject('Error executing "' + cmd + '": ' + stderr);
|
||||
else d.resolve(stdout);
|
||||
});
|
||||
} catch(e) {
|
||||
console.error('error caught: ' + e);
|
||||
d.reject(e);
|
||||
}
|
||||
return d.promise;
|
||||
}
|
||||
|
||||
@@ -1,49 +1,42 @@
|
||||
#!/bin/bash
|
||||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance
|
||||
# with the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing,
|
||||
# software distributed under the License is distributed on an
|
||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
# KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#!/usr/bin/env node
|
||||
|
||||
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||
PROJECT_PATH=$( cd "$DIR/../.." && pwd )
|
||||
device_list=$("$DIR/list-devices")
|
||||
if [ $? != 0 ]; then
|
||||
echo "No devices found to deploy to. Please make sure your device is connected"
|
||||
echo " and you can view it using the 'cordova/lib/list-devices' command."
|
||||
exit 2
|
||||
fi
|
||||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
apks=`find $PROJECT_PATH/bin -type f -maxdepth 1 | egrep '\.apk$'`
|
||||
apk_list=($apks)
|
||||
if [[ ${#apk_list[@]} > 0 ]] ; then
|
||||
# handle target
|
||||
read -ra device_array <<< "$device_list"
|
||||
if [[ "$#" -eq 1 ]] ; then
|
||||
# deploy to given target
|
||||
target=${1/--target=/}
|
||||
else
|
||||
# delete trailing space and 'device' after device ID
|
||||
target=${device_array[0]}
|
||||
fi
|
||||
echo "Installing ${apk_list[0]} onto device $target..."
|
||||
adb -s $target install -r ${apk_list[0]};
|
||||
echo "Launching application..."
|
||||
launch_str=$(java -jar "$PROJECT_PATH"/cordova/appinfo.jar "$PROJECT_PATH"/AndroidManifest.xml)
|
||||
adb -s $target shell am start -W -a android.intent.action.MAIN -n $launch_str
|
||||
else
|
||||
echo "Application package not found, could not install to device"
|
||||
echo " make sure your application is built before deploying."
|
||||
exit 2
|
||||
fi
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
|
||||
var device = require('./device'),
|
||||
args = process.argv;
|
||||
|
||||
if(args.length > 2) {
|
||||
var install_target;
|
||||
if (args[2].substring(0, 9) == '--target=') {
|
||||
install_target = args[2].substring(9, args[2].length);
|
||||
device.install(install_target).done(null, function(err) {
|
||||
console.error('ERROR: ' + err);
|
||||
process.exit(2);
|
||||
});
|
||||
} else {
|
||||
console.error('ERROR : argument \'' + args[2] + '\' not recognized.');
|
||||
process.exit(2);
|
||||
}
|
||||
} else {
|
||||
device.install().done(null, function(err) {
|
||||
console.error('ERROR: ' + err);
|
||||
process.exit(2);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -14,12 +14,13 @@
|
||||
:: KIND, either express or implied. See the License for the
|
||||
:: specific language governing permissions and limitations
|
||||
:: under the License.
|
||||
|
||||
@ECHO OFF
|
||||
SET full_path=%~dp0
|
||||
IF EXIST %full_path%cordova.js (
|
||||
cscript "%full_path%cordova.js" install-device %* //nologo
|
||||
SET script_path="%~dp0install-device"
|
||||
IF EXIST %script_path% (
|
||||
node "%script_path%" %*
|
||||
) ELSE (
|
||||
ECHO.
|
||||
ECHO ERROR: Could not find 'cordova.js' in cordova/lib, aborting...>&2
|
||||
ECHO.
|
||||
ECHO ERROR: Could not find 'install-device' script in 'cordova\lib' folder, aborting...>&2
|
||||
EXIT /B 1
|
||||
)
|
||||
)
|
||||
@@ -1,50 +1,38 @@
|
||||
#!/bin/bash
|
||||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance
|
||||
# with the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing,
|
||||
# software distributed under the License is distributed on an
|
||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
# KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#!/usr/bin/env node
|
||||
|
||||
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||
PROJECT_PATH=$( cd "$DIR/../.." && pwd )
|
||||
emulator_list=$("$DIR/list-started-emulators")
|
||||
if [ $? != 0 ]; then
|
||||
echo "No emulators found to deploy to. Please make sure your emulator is started"
|
||||
echo " You can view it using the 'cordova/lib/list-started-emulators' command."
|
||||
echo " You can view created emulator images using the 'cordova/lib/list-emulator-images' command."
|
||||
echo " You can start an emulator image using the 'cordova/lib/start-emulator' command."
|
||||
exit 2
|
||||
fi
|
||||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
apks=`find $PROJECT_PATH/bin -type f -maxdepth 1 | egrep '\.apk$'`
|
||||
apk_list=($apks)
|
||||
if [[ ${#apk_list[@]} > 0 ]] ; then
|
||||
# handle target emulator
|
||||
if [[ "$#" -eq 1 ]] ; then
|
||||
# deploy to given target
|
||||
target=${1/--target=/}
|
||||
else
|
||||
# delete trailing space and 'device' after emulator ID
|
||||
target=${emulator_list[0]}
|
||||
fi
|
||||
echo "Installing ${apk_list[0]} onto emulator $target..."
|
||||
adb -s $target install -r ${apk_list[0]};
|
||||
echo "Launching application..."
|
||||
launch_str=$(java -jar "$PROJECT_PATH"/cordova/appinfo.jar "$PROJECT_PATH"/AndroidManifest.xml)
|
||||
adb -s $target shell am start -W -a android.intent.action.MAIN -n $launch_str
|
||||
else
|
||||
echo "Application package not found, could not install to device"
|
||||
echo " make sure your application is built before deploying."
|
||||
exit 2
|
||||
fi
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
|
||||
var emulator = require('./emulator'),
|
||||
args = process.argv;
|
||||
|
||||
var install_target;
|
||||
if(args.length > 2) {
|
||||
if (args[2].substring(0, 9) == '--target=') {
|
||||
install_target = args[2].substring(9, args[2].length);
|
||||
} else {
|
||||
console.error('ERROR : argument \'' + args[2] + '\' not recognized.');
|
||||
process.exit(2);
|
||||
}
|
||||
}
|
||||
|
||||
emulator.install(install_target).done(null, function(err) {
|
||||
console.error('ERROR: ' + err);
|
||||
process.exit(2);
|
||||
});
|
||||
|
||||
@@ -14,12 +14,13 @@
|
||||
:: KIND, either express or implied. See the License for the
|
||||
:: specific language governing permissions and limitations
|
||||
:: under the License.
|
||||
|
||||
@ECHO OFF
|
||||
SET full_path=%~dp0
|
||||
IF EXIST %full_path%cordova.js (
|
||||
cscript "%full_path%cordova.js" install-emulator %* //nologo
|
||||
SET script_path="%~dp0install-emulator"
|
||||
IF EXIST %script_path% (
|
||||
node "%script_path%" %*
|
||||
) ELSE (
|
||||
ECHO.
|
||||
ECHO ERROR: Could not find 'cordova.js' in cordova/lib, aborting...>&2
|
||||
ECHO.
|
||||
ECHO ERROR: Could not find 'install-emulator' script in 'cordova\lib' folder, aborting...>&2
|
||||
EXIT /B 1
|
||||
)
|
||||
)
|
||||
@@ -1,30 +1,33 @@
|
||||
#!/bin/bash
|
||||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance
|
||||
# with the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing,
|
||||
# software distributed under the License is distributed on an
|
||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
# KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#!/usr/bin/env node
|
||||
|
||||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
|
||||
var devices = require('./device');
|
||||
|
||||
// Usage support for when args are given
|
||||
devices.list().done(function(device_list) {
|
||||
device_list && device_list.forEach(function(dev) {
|
||||
console.log(dev);
|
||||
});
|
||||
}, function(err) {
|
||||
console.error('ERROR: ' + err);
|
||||
process.exit(2);
|
||||
});
|
||||
|
||||
devices=`adb devices | awk '/List of devices attached/ { while(getline > 0) { print }}' | grep 'device' | grep -v 'emulator' | awk '{ print $1; }'`
|
||||
device_list=($devices)
|
||||
if [[ ${#device_list[@]} > 0 ]] ; then
|
||||
for i in ${devices[@]}
|
||||
do
|
||||
echo $i
|
||||
done
|
||||
exit 0
|
||||
else
|
||||
echo "No devices found."
|
||||
exit 2
|
||||
fi
|
||||
|
||||
@@ -14,12 +14,13 @@
|
||||
:: KIND, either express or implied. See the License for the
|
||||
:: specific language governing permissions and limitations
|
||||
:: under the License.
|
||||
|
||||
@ECHO OFF
|
||||
SET full_path=%~dp0
|
||||
IF EXIST %full_path%cordova.js (
|
||||
cscript "%full_path%cordova.js" list-devices //nologo
|
||||
SET script_path="%~dp0list-devices"
|
||||
IF EXIST %script_path% (
|
||||
node "%script_path%" %*
|
||||
) ELSE (
|
||||
ECHO.
|
||||
ECHO ERROR: Could not find 'cordova.js' in cordova/lib, aborting...>&2
|
||||
ECHO.
|
||||
ECHO ERROR: Could not find 'list-devices' script in 'cordova\lib' folder, aborting...>&2
|
||||
EXIT /B 1
|
||||
)
|
||||
)
|
||||
@@ -1,32 +1,32 @@
|
||||
#!/bin/bash
|
||||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance
|
||||
# with the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing,
|
||||
# software distributed under the License is distributed on an
|
||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
# KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#!/usr/bin/env node
|
||||
|
||||
emulator_images=`android list avds | grep "Name:" | cut -f 2 -d ":"`
|
||||
emulator_list=($emulator_images)
|
||||
if [[ ${#emulator_list[@]} > 0 ]] ; then
|
||||
for i in ${emulator_list[@]}
|
||||
do
|
||||
echo $i
|
||||
done
|
||||
exit 0
|
||||
else
|
||||
echo "No emulators found, if you would like to create an emulator follow the instructions"
|
||||
echo " provided here : http://developer.android.com/tools/devices/index.html"
|
||||
echo " Or run 'android create avd --name <name> --target <targetID>' in on the command line."
|
||||
exit 2
|
||||
fi
|
||||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
|
||||
var emulators = require('./emulator');
|
||||
|
||||
// Usage support for when args are given
|
||||
emulators.list_images().done(function(emulator_list) {
|
||||
emulator_list && emulator_list.forEach(function(emu) {
|
||||
console.log(emu.name);
|
||||
});
|
||||
}, function(err) {
|
||||
console.error('ERROR: ' + err);
|
||||
process.exit(2);
|
||||
});
|
||||
|
||||
@@ -14,12 +14,13 @@
|
||||
:: KIND, either express or implied. See the License for the
|
||||
:: specific language governing permissions and limitations
|
||||
:: under the License.
|
||||
|
||||
@ECHO OFF
|
||||
SET full_path=%~dp0
|
||||
IF EXIST %full_path%cordova.js (
|
||||
cscript "%full_path%cordova.js" list-emulator-images //nologo
|
||||
SET script_path="%~dp0list-emulator-images"
|
||||
IF EXIST %script_path% (
|
||||
node "%script_path%" %*
|
||||
) ELSE (
|
||||
ECHO.
|
||||
ECHO ERROR: Could not find 'cordova.js' in cordova/lib, aborting...>&2
|
||||
ECHO ERROR: Could not find 'list-emulator-images' script in 'cordova\lib' folder, aborting...>&2
|
||||
EXIT /B 1
|
||||
)
|
||||
|
||||
@@ -1,32 +1,32 @@
|
||||
#!/bin/bash
|
||||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance
|
||||
# with the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing,
|
||||
# software distributed under the License is distributed on an
|
||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
# KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#!/usr/bin/env node
|
||||
|
||||
devices=`adb devices | awk '/List of devices attached/ { while(getline > 0) { print $1;}}' | grep 'emulator' | grep -v 'offline'`
|
||||
read -ra emulator_list <<< "$devices"
|
||||
if [[ ${#emulator_list[@]} > 0 ]] ; then
|
||||
for i in ${emulator_list[@]}
|
||||
do
|
||||
# remove space and 'device'
|
||||
echo $i
|
||||
done
|
||||
exit 0
|
||||
else
|
||||
echo "No started emulators found (it may still be booting up), you can start an emulator by using the command"
|
||||
echo " 'cordova/lib/start-emulator'"
|
||||
exit 2
|
||||
fi
|
||||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
|
||||
var emulators = require('./emulator');
|
||||
|
||||
// Usage support for when args are given
|
||||
emulators.list_started().done(function(emulator_list) {
|
||||
emulator_list && emulator_list.forEach(function(emu) {
|
||||
console.log(emu);
|
||||
});
|
||||
}, function(err) {
|
||||
console.error('ERROR: ' + err);
|
||||
process.exit(2);
|
||||
});
|
||||
|
||||
@@ -14,12 +14,13 @@
|
||||
:: KIND, either express or implied. See the License for the
|
||||
:: specific language governing permissions and limitations
|
||||
:: under the License.
|
||||
|
||||
@ECHO OFF
|
||||
SET full_path=%~dp0
|
||||
IF EXIST %full_path%cordova.js (
|
||||
cscript "%full_path%cordova.js" list-started-emulators //nologo
|
||||
SET script_path="%~dp0list-started-emulators"
|
||||
IF EXIST %script_path% (
|
||||
node "%script_path%" %*
|
||||
) ELSE (
|
||||
ECHO.
|
||||
ECHO ERROR: Could not find 'cordova.js' in cordova/lib, aborting...>&2
|
||||
ECHO.
|
||||
ECHO ERROR: Could not find 'list-started-emulators' script in 'cordova\lib' folder, aborting...>&2
|
||||
EXIT /B 1
|
||||
)
|
||||
)
|
||||
58
bin/templates/cordova/lib/log.js
vendored
Normal file
58
bin/templates/cordova/lib/log.js
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
|
||||
var shell = require('shelljs'),
|
||||
path = require('path'),
|
||||
os = require('os'),
|
||||
Q = require('q'),
|
||||
child_process = require('child_process'),
|
||||
ROOT = path.join(__dirname, '..', '..');
|
||||
|
||||
/*
|
||||
* Starts running logcat in the shell.
|
||||
* Returns a promise.
|
||||
*/
|
||||
module.exports.run = function() {
|
||||
var cmd = 'adb logcat | grep -v nativeGetEnabledTags';
|
||||
var d = Q.defer();
|
||||
var adb = child_process.spawn('adb', ['logcat'], {cwd: os.tmpdir()});
|
||||
|
||||
adb.stdout.on('data', function(data) {
|
||||
var lines = data ? data.toString().split('\n') : [];
|
||||
var out = lines.filter(function(x) { return x.indexOf('nativeGetEnabledTags') < 0; });
|
||||
console.log(out.join('\n'));
|
||||
});
|
||||
|
||||
adb.stderr.on('data', console.error);
|
||||
adb.on('close', function(code) {
|
||||
if (code > 0) {
|
||||
d.reject('Failed to run logcat command.');
|
||||
} else d.resolve();
|
||||
});
|
||||
|
||||
return d.promise;
|
||||
}
|
||||
|
||||
module.exports.help = function() {
|
||||
console.log('Usage: ' + path.relative(process.cwd(), path.join(ROOT, 'cordova', 'log')));
|
||||
console.log('Gives the logcat output on the command line.');
|
||||
process.exit(0);
|
||||
}
|
||||
79
bin/templates/cordova/lib/plugin-build.gradle
Normal file
79
bin/templates/cordova/lib/plugin-build.gradle
Normal file
@@ -0,0 +1,79 @@
|
||||
/* Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
|
||||
// GENERATED FILE! DO NOT EDIT!
|
||||
|
||||
buildscript {
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
// Switch the Android Gradle plugin version requirement depending on the
|
||||
// installed version of Gradle. This dependency is documented at
|
||||
// http://tools.android.com/tech-docs/new-build-system/version-compatibility
|
||||
// and https://issues.apache.org/jira/browse/CB-8143
|
||||
if (gradle.gradleVersion >= "2.2") {
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:1.0.0+'
|
||||
}
|
||||
} else if (gradle.gradleVersion >= "2.1") {
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:0.14.0+'
|
||||
}
|
||||
} else {
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:0.12.0+'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'android-library'
|
||||
|
||||
dependencies {
|
||||
compile fileTree(dir: 'libs', include: '*.jar')
|
||||
debugCompile project(path: ":CordovaLib", configuration: "debug")
|
||||
releaseCompile project(path: ":CordovaLib", configuration: "release")
|
||||
}
|
||||
|
||||
android {
|
||||
compileSdkVersion cdvCompileSdkVersion
|
||||
buildToolsVersion cdvBuildToolsVersion
|
||||
publishNonDefault true
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_6
|
||||
targetCompatibility JavaVersion.VERSION_1_6
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
main {
|
||||
manifest.srcFile 'AndroidManifest.xml'
|
||||
java.srcDirs = ['src']
|
||||
resources.srcDirs = ['src']
|
||||
aidl.srcDirs = ['src']
|
||||
renderscript.srcDirs = ['src']
|
||||
res.srcDirs = ['res']
|
||||
assets.srcDirs = ['assets']
|
||||
jniLibs.srcDirs = ['libs']
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (file('build-extras.gradle').exists()) {
|
||||
apply from: 'build-extras.gradle'
|
||||
}
|
||||
158
bin/templates/cordova/lib/run.js
vendored
Normal file
158
bin/templates/cordova/lib/run.js
vendored
Normal file
@@ -0,0 +1,158 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
|
||||
var path = require('path'),
|
||||
build = require('./build'),
|
||||
emulator = require('./emulator'),
|
||||
device = require('./device'),
|
||||
shell = require('shelljs'),
|
||||
Q = require('q');
|
||||
|
||||
/*
|
||||
* Runs the application on a device if available.
|
||||
* If no device is found, it will use a started emulator.
|
||||
* If no started emulators are found it will attempt to start an avd.
|
||||
* If no avds are found it will error out.
|
||||
* Returns a promise.
|
||||
*/
|
||||
module.exports.run = function(args) {
|
||||
var buildFlags = [];
|
||||
var install_target;
|
||||
var list = false;
|
||||
|
||||
for (var i=2; i<args.length; i++) {
|
||||
if (/^--(debug|release|ant|gradle|nobuild|versionCode=|minSdkVersion=|gradleArg=)/.exec(args[i])) {
|
||||
buildFlags.push(args[i]);
|
||||
} else if (args[i] == '--device') {
|
||||
install_target = '--device';
|
||||
} else if (args[i] == '--emulator') {
|
||||
install_target = '--emulator';
|
||||
} else if (/^--target=/.exec(args[i])) {
|
||||
install_target = args[i].substring(9, args[i].length);
|
||||
} else if (args[i] == '--list') {
|
||||
list = true;
|
||||
} else {
|
||||
console.warn('Option \'' + args[i] + '\' not recognized (ignoring).');
|
||||
}
|
||||
}
|
||||
|
||||
if (list) {
|
||||
var output = '';
|
||||
var temp = '';
|
||||
if (!install_target) {
|
||||
output += 'Available Android Devices:\n';
|
||||
temp = shell.exec(path.join(__dirname, 'list-devices'), {silent:true}).output;
|
||||
temp = temp.replace(/^(?=[^\s])/gm, '\t');
|
||||
output += temp;
|
||||
output += 'Available Android Virtual Devices:\n';
|
||||
temp = shell.exec(path.join(__dirname, 'list-emulator-images'), {silent:true}).output;
|
||||
temp = temp.replace(/^(?=[^\s])/gm, '\t');
|
||||
output += temp;
|
||||
} else if (install_target == '--emulator') {
|
||||
output += 'Available Android Virtual Devices:\n';
|
||||
temp = shell.exec(path.join(__dirname, 'list-emulator-images'), {silent:true}).output;
|
||||
temp = temp.replace(/^(?=[^\s])/gm, '\t');
|
||||
output += temp;
|
||||
} else if (install_target == '--device') {
|
||||
output += 'Available Android Devices:\n';
|
||||
temp = shell.exec(path.join(__dirname, 'list-devices'), {silent:true}).output;
|
||||
temp = temp.replace(/^(?=[^\s])/gm, '\t');
|
||||
output += temp;
|
||||
}
|
||||
console.log(output);
|
||||
return;
|
||||
}
|
||||
|
||||
return Q()
|
||||
.then(function() {
|
||||
if (!install_target) {
|
||||
// no target given, deploy to device if available, otherwise use the emulator.
|
||||
return device.list()
|
||||
.then(function(device_list) {
|
||||
if (device_list.length > 0) {
|
||||
console.log('WARNING : No target specified, deploying to device \'' + device_list[0] + '\'.');
|
||||
install_target = device_list[0];
|
||||
} else {
|
||||
console.log('WARNING : No target specified, deploying to emulator');
|
||||
install_target = '--emulator';
|
||||
}
|
||||
});
|
||||
}
|
||||
}).then(function() {
|
||||
if (install_target == '--device') {
|
||||
return device.resolveTarget(null);
|
||||
} else if (install_target == '--emulator') {
|
||||
// Give preference to any already started emulators. Else, start one.
|
||||
return emulator.list_started()
|
||||
.then(function(started) {
|
||||
return started && started.length > 0 ? started[0] : emulator.start();
|
||||
}).then(function(emulatorId) {
|
||||
return emulator.resolveTarget(emulatorId);
|
||||
});
|
||||
}
|
||||
// They specified a specific device/emulator ID.
|
||||
return device.list()
|
||||
.then(function(devices) {
|
||||
if (devices.indexOf(install_target) > -1) {
|
||||
return device.resolveTarget(install_target);
|
||||
}
|
||||
return emulator.list_started()
|
||||
.then(function(started_emulators) {
|
||||
if (started_emulators.indexOf(install_target) > -1) {
|
||||
return emulator.resolveTarget(install_target);
|
||||
}
|
||||
return emulator.list_images()
|
||||
.then(function(avds) {
|
||||
// if target emulator isn't started, then start it.
|
||||
for (avd in avds) {
|
||||
if (avds[avd].name == install_target) {
|
||||
return emulator.start(install_target)
|
||||
.then(function(emulatorId) {
|
||||
return emulator.resolveTarget(emulatorId);
|
||||
});
|
||||
}
|
||||
}
|
||||
return Q.reject('Target \'' + install_target + '\' not found, unable to run project');
|
||||
});
|
||||
});
|
||||
});
|
||||
}).then(function(resolvedTarget) {
|
||||
return build.run(buildFlags, resolvedTarget).then(function(buildResults) {
|
||||
if (resolvedTarget.isEmulator) {
|
||||
return emulator.install(resolvedTarget, buildResults);
|
||||
}
|
||||
return device.install(resolvedTarget, buildResults);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
module.exports.help = function(args) {
|
||||
console.log('Usage: ' + path.relative(process.cwd(), args[1]) + ' [options]');
|
||||
console.log('Build options :');
|
||||
console.log(' --debug : Builds project in debug mode');
|
||||
console.log(' --release : Builds project in release mode');
|
||||
console.log(' --nobuild : Runs the currently built project without recompiling');
|
||||
console.log('Deploy options :');
|
||||
console.log(' --device : Will deploy the built project to a device');
|
||||
console.log(' --emulator : Will deploy the built project to an emulator if one exists');
|
||||
console.log(' --target=<target_id> : Installs to the target with the specified id.');
|
||||
process.exit(0);
|
||||
}
|
||||
50
bin/templates/cordova/lib/spawn.js
vendored
Normal file
50
bin/templates/cordova/lib/spawn.js
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
|
||||
var child_process = require('child_process'),
|
||||
Q = require('q');
|
||||
var isWindows = process.platform.slice(0, 3) == 'win';
|
||||
|
||||
// Takes a command and optional current working directory.
|
||||
module.exports = function(cmd, args, opt_cwd) {
|
||||
var d = Q.defer();
|
||||
var opts = { cwd: opt_cwd, stdio: 'inherit' };
|
||||
try {
|
||||
// Work around spawn not being able to find .bat files.
|
||||
if (isWindows) {
|
||||
args = [['/s', '/c', '"' + [cmd].concat(args).map(function(a){if (/^[^"].* .*[^"]/.test(a)) return '"' + a + '"'; return a;}).join(' ')+'"'].join(' ')];
|
||||
cmd = 'cmd';
|
||||
opts.windowsVerbatimArguments = true;
|
||||
}
|
||||
var child = child_process.spawn(cmd, args, opts);
|
||||
child.on('exit', function(code) {
|
||||
if (code) {
|
||||
d.reject('Error code ' + code + ' for command: ' + cmd + ' with args: ' + args);
|
||||
} else {
|
||||
d.resolve();
|
||||
}
|
||||
});
|
||||
} catch(e) {
|
||||
console.error('error caught: ' + e);
|
||||
d.reject(e);
|
||||
}
|
||||
return d.promise;
|
||||
};
|
||||
@@ -1,91 +1,39 @@
|
||||
#!/bin/bash
|
||||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance
|
||||
# with the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing,
|
||||
# software distributed under the License is distributed on an
|
||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
# KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#!/usr/bin/env node
|
||||
|
||||
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||
PROJECT_PATH=$( cd "$( dirname "$0" )/../.." && pwd )
|
||||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
function dot {
|
||||
sleep 1
|
||||
echo -n "."
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
|
||||
var emulator = require('./emulator'),
|
||||
args = process.argv;
|
||||
|
||||
var install_target;
|
||||
if(args.length > 2) {
|
||||
if (args[2].substring(0, 9) == '--target=') {
|
||||
install_target = args[2].substring(9, args[2].length);
|
||||
} else {
|
||||
console.error('ERROR : argument \'' + args[2] + '\' not recognized.');
|
||||
process.exit(2);
|
||||
}
|
||||
}
|
||||
|
||||
function wait_for_emulator {
|
||||
local i="0"
|
||||
echo -n "Waiting for emulator"
|
||||
emulator_string=$($DIR/list-started-emulators)
|
||||
while [ $? != 0 ]
|
||||
do
|
||||
dot
|
||||
i=$[i+1]
|
||||
emulator_string=$($DIR/list-started-emulators)
|
||||
done
|
||||
read -ra target <<< "$emulator_string"
|
||||
echo ""
|
||||
echo -n "Waiting for it to boot up (this can take a while)"
|
||||
while [ $i -lt 300 ]
|
||||
do
|
||||
boot_anim=$(adb -s $target shell getprop init.svc.bootanim 2>&1)
|
||||
if [[ "$boot_anim" =~ "stopped" ]] ; then
|
||||
break
|
||||
else
|
||||
i=$[i+1]
|
||||
dot
|
||||
fi
|
||||
done
|
||||
# Device timeout: emulator has not started in time
|
||||
if [ $i -eq 300 ]
|
||||
then
|
||||
echo ""
|
||||
echo "Emulator timeout!"
|
||||
exit 69
|
||||
else
|
||||
echo ""
|
||||
echo "Connected!"
|
||||
fi
|
||||
# Unlock the device
|
||||
adb -s $target shell input keyevent 82
|
||||
exit 0
|
||||
}
|
||||
emulator.start(install_target).done(null, function(err) {
|
||||
console.error('ERROR: ' + err);
|
||||
process.exit(2);
|
||||
});
|
||||
|
||||
emulator_images=$("$DIR/list-emulator-images")
|
||||
if [ $? != 0 ]; then
|
||||
echo "No emulators found, if you would like to create an emulator follow the instructions"
|
||||
echo " provided here : http://developer.android.com/tools/devices/index.html"
|
||||
echo " Or run 'android create avd --name <name> --target <targetID>' in on the command line."
|
||||
exit 2
|
||||
fi
|
||||
|
||||
# if target emulator is provided
|
||||
if [[ "$#" -eq 1 ]] ; then
|
||||
# check that it exists
|
||||
if [[ $emulator_images =~ $1 ]] ; then
|
||||
#xterm -e emulator -avd $1 &
|
||||
emulator -avd $1 1> /dev/null 2>&1 &
|
||||
else
|
||||
echo "Could not find the provided emulator '$1', make sure the emulator exists"
|
||||
echo " by checking 'cordova/lib/list-emulator-images'"
|
||||
exit 2
|
||||
fi
|
||||
else
|
||||
# start first emulator
|
||||
read -ra emulator_list <<< "$emulator_images"
|
||||
#xterm -e emulator -avd ${emulator_list[0]} &
|
||||
emulator -avd ${emulator_list[0]} 1> /dev/null 2>&1 &
|
||||
fi
|
||||
|
||||
wait_for_emulator
|
||||
|
||||
@@ -14,12 +14,13 @@
|
||||
:: KIND, either express or implied. See the License for the
|
||||
:: specific language governing permissions and limitations
|
||||
:: under the License.
|
||||
|
||||
@ECHO OFF
|
||||
SET full_path=%~dp0
|
||||
IF EXIST %full_path%cordova.js (
|
||||
cscript "%full_path%cordova.js" start-emulator %* //nologo
|
||||
SET script_path="%~dp0start-emulator"
|
||||
IF EXIST %script_path% (
|
||||
node "%script_path%" %*
|
||||
) ELSE (
|
||||
ECHO.
|
||||
ECHO ERROR: Could not find 'cordova.js' in cordova/lib, aborting...>&2
|
||||
ECHO.
|
||||
ECHO ERROR: Could not find 'start-emulator' script in 'cordova\lib' folder, aborting...>&2
|
||||
EXIT /B 1
|
||||
)
|
||||
)
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user