longbow 0.3.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +4 -4
- data/README.md +16 -2
- data/lib/longbow/commands/aim.rb +70 -0
- data/lib/longbow/commands.rb +2 -1
- data/lib/longbow/version.rb +1 -1
- data/resources/capture.js +57 -0
- data/resources/ui-screen-shooter.sh +211 -0
- data/resources/unix_instruments.sh +67 -0
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 15fa151122cbcc2370b29b534deb29ab20963d2b
|
4
|
+
data.tar.gz: fe61af58b2639bc7ccb43bc4ae7a6ed637bad914
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c12ce676cd115c74872b4830352e5813fce07c487830652fb8870333f64b81fb721893c88ac238bdf9fa032bd2ba18c8c6369d9a34ae171511a37ac30b7ea226
|
7
|
+
data.tar.gz: 29dad19263ce1460376258148047f71fc94fd860f72595d680f5d58ec14dbb1357feacc0b666e4f3af8cab7b855950ad3b5ed0c930b95640b23be78ecfd65c62
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
longbow (0.
|
4
|
+
longbow (0.4.0)
|
5
5
|
bundler (~> 1.3)
|
6
6
|
commander (~> 4.1)
|
7
7
|
dotenv (~> 0.7)
|
@@ -17,20 +17,20 @@ GEM
|
|
17
17
|
i18n (~> 0.6, >= 0.6.4)
|
18
18
|
multi_json (~> 1.0)
|
19
19
|
colored (1.2)
|
20
|
-
commander (4.
|
20
|
+
commander (4.2.0)
|
21
21
|
highline (~> 1.6.11)
|
22
22
|
dotenv (0.11.1)
|
23
23
|
dotenv-deployment (~> 0.0.2)
|
24
24
|
dotenv-deployment (0.0.2)
|
25
25
|
fileutils (0.7)
|
26
26
|
rmagick (>= 2.13.1)
|
27
|
-
highline (1.6.
|
27
|
+
highline (1.6.21)
|
28
28
|
i18n (0.6.9)
|
29
29
|
json (1.8.1)
|
30
30
|
multi_json (1.9.3)
|
31
31
|
rake (10.1.1)
|
32
32
|
rmagick (2.13.2)
|
33
|
-
xcodeproj (0.
|
33
|
+
xcodeproj (0.17.0)
|
34
34
|
activesupport (~> 3.0)
|
35
35
|
colored (~> 1.2)
|
36
36
|
|
data/README.md
CHANGED
@@ -2,19 +2,22 @@
|
|
2
2
|
|
3
3
|
**Problem**
|
4
4
|
|
5
|
-
One codebase. Multiple App Store submission targets with different icons, launch images, info.plist keys, etc.
|
5
|
+
One codebase. Multiple App Store submission targets with different icons, launch images, info.plist keys, screenshots, etc.
|
6
6
|
|
7
7
|
**Solution**
|
8
8
|
|
9
9
|
```
|
10
10
|
$ longbow install
|
11
11
|
$ longbow shoot
|
12
|
+
$ longbow aim
|
12
13
|
```
|
13
14
|
|
14
15
|
**About**
|
15
16
|
|
16
17
|
Longbow is a command-line run ruby gem that duplicates the main target in your `.xcworkspace` or `.xcodeproj` file, then reads from a JSON file to fill out the rest of your new target. It looks for certain keys and does things like taking an icon image and resizing it for the various icons you'll need, and adding keys to the info.plist file for that target. The goal was to be practically autonomous in creating new targets and apps.
|
17
18
|
|
19
|
+
Additionally, it can create screenshots for each target app store submission. You write a simple UIAutomation script (it's just JavaScript) and Longbow takes care of taking the screenshots for each combination of target, device, and language.
|
20
|
+
|
18
21
|
**Requirements**
|
19
22
|
|
20
23
|
Longbow requires Xcode 5+, and your app must use the new .xcassets paradigm for icons, launch screens, etc.
|
@@ -43,7 +46,7 @@ Run `longbow install` in the directory where your `.xcworkspace` or `.xcodeproj`
|
|
43
46
|
|
44
47
|
Here's a basic gist of how to format your `longbow.json` file:
|
45
48
|
|
46
|
-
```
|
49
|
+
```json
|
47
50
|
{
|
48
51
|
"targets":[
|
49
52
|
{
|
@@ -115,6 +118,17 @@ If you leave off the `-n` option, it will run for all targets in the `longbow.js
|
|
115
118
|
|
116
119
|
`--help` will fill you in on what you need to do for an action.
|
117
120
|
|
121
|
+
## Taking Screenshots
|
122
|
+
|
123
|
+
So you've created all your targets and finished the first version of the app - now you need the screen shots to submit it to the App Store.
|
124
|
+
|
125
|
+
First you'll need to write a single UIAutomation script to take the screenshots. You can see [Apple's Documentation](https://developer.apple.com/library/ios/documentation/DeveloperTools/Reference/UIAutomationRef/_index.html) for more information on writing the script. The part we're primarily concerned with is the captureLocalizedScreenshot() method provided by Longbow. This method will take the screenshot with a consistent naming scheme and place it in a folder for each target.
|
126
|
+
|
127
|
+
`captureLocalizedScreenshot("homeScreen");` will create ~/Desktop/screenshots/TargetName/en-US/iOS-4-in\_\_\_portrait\_\_\_homeScreen.png
|
128
|
+
|
129
|
+
Once you've created your automation script, you can run it by calling `longbow aim`. This command will generate a variation of your UIAutomation script for each target, then handle running it for each target. Grab a drink, depending on your script and your number of targets, this may take a while.
|
130
|
+
|
131
|
+
|
118
132
|
## The Future
|
119
133
|
|
120
134
|
* Unit Tests
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'longbow/colors'
|
3
|
+
require 'longbow/targets'
|
4
|
+
require 'longbow/images'
|
5
|
+
require 'longbow/json'
|
6
|
+
require 'json'
|
7
|
+
|
8
|
+
command :aim do |c|
|
9
|
+
c.syntax = 'longbow aim'
|
10
|
+
c.syntax = 'Takes screenshots for each target in your workspace or project based on a UIAutomation script.'
|
11
|
+
c.description = ''
|
12
|
+
c.option '-s', '--script SCRIPT', 'Script used to get the app into the proper state for each screenshot'
|
13
|
+
c.option '-d', '--directory DIRECTORY', 'Path where the .xcodeproj or .xcworkspace file && the longbow.json file live.'
|
14
|
+
c.option '-u', '--url URL', 'URL of a longbow formatted JSON file.'
|
15
|
+
c.option '-n', '--name NAME', 'Name of the target to get a screenshot for.'
|
16
|
+
|
17
|
+
c.action do |args, options|
|
18
|
+
# Check for newer version
|
19
|
+
Longbow::check_for_newer_version unless $nolog
|
20
|
+
|
21
|
+
# Set Up
|
22
|
+
@script = options.script ? options.script : nil
|
23
|
+
@directory = options.directory ? options.directory : Dir.pwd
|
24
|
+
@url = options.url ? options.url : nil
|
25
|
+
@target_name = options.name
|
26
|
+
@targets = []
|
27
|
+
|
28
|
+
# Create JSON object
|
29
|
+
if @url
|
30
|
+
obj = Longbow::json_object_from_url @url
|
31
|
+
else
|
32
|
+
obj = Longbow::json_object_from_directory @directory
|
33
|
+
end
|
34
|
+
|
35
|
+
# Break if Bad
|
36
|
+
unless obj || Longbow::lint_json_object(obj)
|
37
|
+
Longbow::red "\n Invalid JSON. Please lint the file, and try again.\n"
|
38
|
+
next
|
39
|
+
end
|
40
|
+
|
41
|
+
# Check for Target Name
|
42
|
+
if @target_name
|
43
|
+
obj['targets'].each do |t|
|
44
|
+
@targets << t if t['name'] == @target_name
|
45
|
+
end
|
46
|
+
|
47
|
+
if @targets.length == 0
|
48
|
+
Longbow::red "\n Couldn't find a target named #{@target_name} in the longbow.json file.\n"
|
49
|
+
next
|
50
|
+
end
|
51
|
+
else
|
52
|
+
@targets = obj['targets']
|
53
|
+
end
|
54
|
+
|
55
|
+
resources_path = File.dirname(__FILE__) + '/../../../resources'
|
56
|
+
|
57
|
+
FileUtils.cp "#{resources_path}/capture.js", "capture.js"
|
58
|
+
|
59
|
+
@targets.each do |t|
|
60
|
+
Longbow::blue " Running screenshooter for #{t['name']}"
|
61
|
+
begin
|
62
|
+
`#{resources_path}/ui-screen-shooter.sh ~/Desktop/screenshots/#{t['name']} #{t['name']} #{@script}`
|
63
|
+
rescue
|
64
|
+
Longbow::red "Failed while running screenshooter for #{t['name']}"
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
FileUtils.rm "capture.js"
|
69
|
+
end
|
70
|
+
end
|
data/lib/longbow/commands.rb
CHANGED
data/lib/longbow/version.rb
CHANGED
@@ -0,0 +1,57 @@
|
|
1
|
+
// Copyright (c) 2012 Jonathan Penn (http://cocoamanifest.net/)
|
2
|
+
|
3
|
+
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
// of this software and associated documentation files (the "Software"), to deal
|
5
|
+
// in the Software without restriction, including without limitation the rights
|
6
|
+
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
// copies of the Software, and to permit persons to whom the Software is
|
8
|
+
// furnished to do so, subject to the following conditions:
|
9
|
+
|
10
|
+
// The above copyright notice and this permission notice shall be included in
|
11
|
+
// all copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
// THE SOFTWARE.
|
20
|
+
|
21
|
+
// captureLocalizedScreenshot(name)
|
22
|
+
//
|
23
|
+
// Tells the local target to take a screen shot and names the file after the
|
24
|
+
// state of the simulator like so:
|
25
|
+
//
|
26
|
+
// [model]___[orientation]___[name].png
|
27
|
+
//
|
28
|
+
// `model` is the model of the device (iphone, iphone5, ipad)
|
29
|
+
// `orientation` is...well...duh!
|
30
|
+
// `name` is what you passed in to the function
|
31
|
+
//
|
32
|
+
// Screenshots are saved along with the trace results in UI Automation. See
|
33
|
+
// `run_screenshooter.sh` for examples on how to pull those images out and put
|
34
|
+
// them wherever you want.
|
35
|
+
//
|
36
|
+
function captureLocalizedScreenshot(name) {
|
37
|
+
var target = UIATarget.localTarget();
|
38
|
+
var model = target.model();
|
39
|
+
var rect = target.rect();
|
40
|
+
|
41
|
+
var orientation = "portrait";
|
42
|
+
if (rect.size.height < rect.size.width) orientation = "landscape";
|
43
|
+
|
44
|
+
if (model.match(/iPhone/)) {
|
45
|
+
if ((orientation == "portrait" && rect.size.height > 480) || (orientation == "landscape" && rect.size.width > 480)) {
|
46
|
+
model = "iOS-4-in";
|
47
|
+
} else {
|
48
|
+
model = "iOS-3.5-in";
|
49
|
+
}
|
50
|
+
} else {
|
51
|
+
model = "iOS-iPad";
|
52
|
+
}
|
53
|
+
|
54
|
+
var parts = [model, orientation, name];
|
55
|
+
target.captureScreenWithName(parts.join("___"));
|
56
|
+
}
|
57
|
+
|
@@ -0,0 +1,211 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
# Copyright (c) 2012 Jonathan Penn (http://cocoamanifest.net/)
|
3
|
+
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
5
|
+
# of this software and associated documentation files (the "Software"), to deal
|
6
|
+
# in the Software without restriction, including without limitation the rights
|
7
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
8
|
+
# copies of the Software, and to permit persons to whom the Software is
|
9
|
+
# furnished to do so, subject to the following conditions:
|
10
|
+
|
11
|
+
# The above copyright notice and this permission notice shall be included in
|
12
|
+
# all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
15
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
16
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
17
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
18
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
19
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
20
|
+
# THE SOFTWARE.
|
21
|
+
|
22
|
+
|
23
|
+
# Tell bash that we want the whole script to fail if any part fails.
|
24
|
+
set -e
|
25
|
+
|
26
|
+
# We require a parameter for where to put the results and the test script
|
27
|
+
destination="$1"
|
28
|
+
scheme_name="$2"
|
29
|
+
ui_script="$3"
|
30
|
+
|
31
|
+
# The locale identifiers for the languages you want to shoot
|
32
|
+
# Use the format like en-US zh-Hans for filenames compatible with iTunes
|
33
|
+
# connect upload tool
|
34
|
+
# FYI: get the locale names for you existing app with iTMSTransporter and:
|
35
|
+
# grep locale ~/Desktop/*.itmsp/metadata.xml | grep name | sort -u
|
36
|
+
languages="en-US"
|
37
|
+
|
38
|
+
# The simulators we want to run the script against, declared as a Bash array.
|
39
|
+
# Run `instruments -w help` to get a list of all the possible string values.
|
40
|
+
#declare -a simulators=(
|
41
|
+
#"iPhone Retina (3.5-inch) - Simulator - iOS 7.1"
|
42
|
+
#"iPhone Retina (4-inch) - Simulator - iOS 7.1"
|
43
|
+
#"iPad Retina - Simulator - iOS 7.1"
|
44
|
+
#)
|
45
|
+
declare -a simulators=(
|
46
|
+
"iPhone Retina (3.5-inch) - Simulator - iOS 7.1"
|
47
|
+
"iPhone Retina (4-inch) - Simulator - iOS 7.1"
|
48
|
+
)
|
49
|
+
|
50
|
+
function main {
|
51
|
+
_check_destination
|
52
|
+
_check_ui_script
|
53
|
+
_check_scheme_name
|
54
|
+
_xcode clean build
|
55
|
+
_reset_sim
|
56
|
+
|
57
|
+
for simulator in "${simulators[@]}"; do
|
58
|
+
for language in $languages; do
|
59
|
+
_clean_trace_results_dir
|
60
|
+
_run_automation "$ui_script" "$language" "$simulator"
|
61
|
+
_copy_screenshots "$language"
|
62
|
+
done
|
63
|
+
done
|
64
|
+
|
65
|
+
_close_sim
|
66
|
+
|
67
|
+
echo
|
68
|
+
echo "Screenshots complete!"
|
69
|
+
}
|
70
|
+
|
71
|
+
# Global variables to keep track of where everything goes
|
72
|
+
tmp_dir="/tmp"
|
73
|
+
build_dir="$tmp_dir/screen_shooter"
|
74
|
+
bundle_dir="$build_dir/app.app"
|
75
|
+
trace_results_dir="$build_dir/traces"
|
76
|
+
|
77
|
+
function _check_destination {
|
78
|
+
# Abort if the destination directory already exists. Better safe than sorry.
|
79
|
+
|
80
|
+
if [ -z "$destination" ]; then
|
81
|
+
destination="$HOME/Desktop/screenshots"
|
82
|
+
fi
|
83
|
+
if [ -d "$destination" ]; then
|
84
|
+
echo "Destination directory \"$destination\" already exists! Moving Directory."
|
85
|
+
mv "$destination" "$HOME/Desktop/screenshots$(date +"%Y%m%d%H%M")"
|
86
|
+
fi
|
87
|
+
}
|
88
|
+
|
89
|
+
function _check_ui_script {
|
90
|
+
# Abort if the UI script does not exist.
|
91
|
+
|
92
|
+
if [ -z "$ui_script" ]; then
|
93
|
+
ui_script="./shoot_the_screens.js"
|
94
|
+
fi
|
95
|
+
if [ ! -f "$ui_script" ]; then
|
96
|
+
echo "UI script \"$ui_script\" does not exist! Aborting."
|
97
|
+
exit 1
|
98
|
+
fi
|
99
|
+
}
|
100
|
+
|
101
|
+
function _check_scheme_name {
|
102
|
+
if [ -z "$scheme_name" ]; then
|
103
|
+
scheme_name=$(basename *.xcworkspace .xcworkspace)
|
104
|
+
echo "No scheme name specified, using the default."
|
105
|
+
fi
|
106
|
+
}
|
107
|
+
|
108
|
+
function _xcode {
|
109
|
+
# A wrapper around `xcodebuild` that tells it to build the app in the temp
|
110
|
+
# directory. If your app uses workspaces or special schemes, you'll need to
|
111
|
+
# specify them here.
|
112
|
+
#
|
113
|
+
# Use `man xcodebuild` for more information on how to build your project.
|
114
|
+
if test -n "$(find . -maxdepth 1 -name '*.xcworkspace' -print -quit)"
|
115
|
+
then
|
116
|
+
base=$(basename *.xcworkspace .xcworkspace)
|
117
|
+
# First build omits PRODUCT_NAME
|
118
|
+
# Do NOT ask me why you need to build this twice for it to work
|
119
|
+
# or how I became to know this fact
|
120
|
+
xcodebuild -sdk "iphonesimulator$ios_version" \
|
121
|
+
CONFIGURATION_BUILD_DIR="$build_dir/build" \
|
122
|
+
-workspace $base.xcworkspace -scheme $scheme_name -configuration AdHoc \
|
123
|
+
DSTROOT=$build_dir \
|
124
|
+
OBJROOT=$build_dir \
|
125
|
+
SYMROOT=$build_dir \
|
126
|
+
ONLY_ACTIVE_ARCH=NO \
|
127
|
+
"$@"
|
128
|
+
xcodebuild -sdk "iphonesimulator$ios_version" \
|
129
|
+
CONFIGURATION_BUILD_DIR="$build_dir/build" \
|
130
|
+
PRODUCT_NAME=app \
|
131
|
+
-workspace $base.xcworkspace -scheme $scheme_name -configuration AdHoc \
|
132
|
+
DSTROOT=$build_dir \
|
133
|
+
OBJROOT=$build_dir \
|
134
|
+
SYMROOT=$build_dir \
|
135
|
+
ONLY_ACTIVE_ARCH=NO \
|
136
|
+
"$@"
|
137
|
+
cp -r "$build_dir/build/app.app" "$build_dir"
|
138
|
+
else
|
139
|
+
xcodebuild -sdk "iphonesimulator$ios_version" \
|
140
|
+
CONFIGURATION_BUILD_DIR=$build_dir \
|
141
|
+
PRODUCT_NAME=app \
|
142
|
+
"$@"
|
143
|
+
fi
|
144
|
+
}
|
145
|
+
|
146
|
+
function _clean_trace_results_dir {
|
147
|
+
# Removes the trace results directory. We need to do this because Instruments
|
148
|
+
# keeps appending new trace runs and it's simpler for us to always assume
|
149
|
+
# there's just one run recorded where we look for screenshots.
|
150
|
+
|
151
|
+
rm -rf "$trace_results_dir"
|
152
|
+
mkdir -p "$trace_results_dir"
|
153
|
+
}
|
154
|
+
|
155
|
+
function _run_automation {
|
156
|
+
# Runs the UI Automation JavaScript file that actually takes the screenshots.
|
157
|
+
|
158
|
+
automation_script="$1"
|
159
|
+
language="$2"
|
160
|
+
simulator="$3"
|
161
|
+
|
162
|
+
echo "Running automation script \"$automation_script\"
|
163
|
+
for \"$simulator\"
|
164
|
+
in language \"${language}\"..."
|
165
|
+
|
166
|
+
dev_tools_dir=`xcode-select -print-path`
|
167
|
+
tracetemplate="$dev_tools_dir/../Applications/Instruments.app/Contents/PlugIns/AutomationInstrument.bundle/Contents/Resources/Automation.tracetemplate"
|
168
|
+
|
169
|
+
# Check out the `unix_instruments.sh` script to see why we need this wrapper.
|
170
|
+
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
171
|
+
"$DIR"/unix_instruments.sh \
|
172
|
+
-w "$simulator" \
|
173
|
+
-D "$trace_results_dir/trace" \
|
174
|
+
-t "$tracetemplate" \
|
175
|
+
$bundle_dir \
|
176
|
+
-e UIARESULTSPATH "$trace_results_dir" \
|
177
|
+
-e UIASCRIPT "$automation_script" \
|
178
|
+
-AppleLanguages "($language)" \
|
179
|
+
-AppleLocale "$language" \
|
180
|
+
"$@"
|
181
|
+
|
182
|
+
find $trace_results_dir/Run\ 1/ -name *landscape*png -type f -exec sips -r -90 \{\} \;
|
183
|
+
}
|
184
|
+
|
185
|
+
function _copy_screenshots {
|
186
|
+
# Since we're always clearing out the trace results before every run, we can
|
187
|
+
# assume that any screenshots were saved in the "Run 1" directory. Copy them
|
188
|
+
# to the destination's language folder!
|
189
|
+
|
190
|
+
language="$1"
|
191
|
+
|
192
|
+
mkdir -p "$destination/$language"
|
193
|
+
cp $trace_results_dir/Run\ 1/*.png "$destination/$language"
|
194
|
+
}
|
195
|
+
|
196
|
+
function _reset_sim {
|
197
|
+
count=`ps aux | grep [l]aunchd_sim | wc -l`
|
198
|
+
if [ $count -ne 0 ]
|
199
|
+
then
|
200
|
+
kill -9 $(ps -ef | grep [l]aunchd_sim | awk {'print $2'})
|
201
|
+
fi
|
202
|
+
}
|
203
|
+
|
204
|
+
function _close_sim {
|
205
|
+
# I know, I know. It says "iPhone Simulator". For some reason,
|
206
|
+
# that's the only way Applescript can identify it.
|
207
|
+
osascript -e "tell application \"iPhone Simulator\" to quit"
|
208
|
+
}
|
209
|
+
|
210
|
+
main
|
211
|
+
|
@@ -0,0 +1,67 @@
|
|
1
|
+
#!/usr/bin/env bash
|
2
|
+
#
|
3
|
+
# Copyright (c) 2013 Jonathan Penn (http://cocoamanifest.net)
|
4
|
+
#
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
# of this software and associated documentation files (the "Software"), to deal
|
7
|
+
# in the Software without restriction, including without limitation the rights
|
8
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
# copies of the Software, and to permit persons to whom the Software is
|
10
|
+
# furnished to do so, subject to the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be included in all
|
13
|
+
# copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
# SOFTWARE.
|
22
|
+
#
|
23
|
+
|
24
|
+
|
25
|
+
# unix_instruments
|
26
|
+
#
|
27
|
+
# A wrapper around `instruments` that returns a proper unix status code
|
28
|
+
# depending on whether the run failed or not. Alas, Apple's instruments tool
|
29
|
+
# doesn't care about unix status codes, so I must grep for the "Fail:" string
|
30
|
+
# and figure it out myself. As long as the command doesn't output that string
|
31
|
+
# anywhere else inside it, then it should work.
|
32
|
+
#
|
33
|
+
# I use a tee pipe to capture the output and deliver it to stdout
|
34
|
+
#
|
35
|
+
# Author: Jonathan Penn (jonathan@cocoamanifest.net)
|
36
|
+
#
|
37
|
+
|
38
|
+
set -e # Bomb on any script errors
|
39
|
+
|
40
|
+
run_instruments() {
|
41
|
+
# Pipe to `tee` using a temporary file so everything is sent to standard out
|
42
|
+
# and we have the output to check for errors.
|
43
|
+
output=$(mktemp -t unix-instruments)
|
44
|
+
instruments "$@" 2>&1 | tee $output
|
45
|
+
|
46
|
+
# Process the instruments output looking for anything that resembles a fail
|
47
|
+
# message
|
48
|
+
cat $output | get_error_status
|
49
|
+
}
|
50
|
+
|
51
|
+
get_error_status() {
|
52
|
+
# Catch "Instruments Trace Error"
|
53
|
+
# Catch "Instruments Usage Error"
|
54
|
+
# Catch "00-00-00 00:00:00 +000 Fail:"
|
55
|
+
# Catch "00-00-00 00:00:00 +000 Error:"
|
56
|
+
# Catch "00-00-00 00:00:00 +000 None: Script threw an uncaught JavaScript error"
|
57
|
+
ruby -e 'exit 1 if STDIN.read =~ /Instruments Usage Error|Instruments Trace Error|^\d+-\d+-\d+ \d+:\d+:\d+ [-+]\d+ (Fail:|Error:|None: Script threw an uncaught JavaScript error)/'
|
58
|
+
}
|
59
|
+
|
60
|
+
# Running this file with "----test" will try to parse an error out of whatever
|
61
|
+
# is handed in to it from stdin. Use this method to double check your work if
|
62
|
+
# you need a custom "get_error_status" function above.
|
63
|
+
if [[ $1 == "----test" ]]; then
|
64
|
+
get_error_status
|
65
|
+
else
|
66
|
+
run_instruments "$@"
|
67
|
+
fi
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: longbow
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Intermark Interactive
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-07-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -134,6 +134,7 @@ files:
|
|
134
134
|
- ./Gemfile
|
135
135
|
- ./Gemfile.lock
|
136
136
|
- ./lib/longbow/colors.rb
|
137
|
+
- ./lib/longbow/commands/aim.rb
|
137
138
|
- ./lib/longbow/commands/install.rb
|
138
139
|
- ./lib/longbow/commands/shoot.rb
|
139
140
|
- ./lib/longbow/commands.rb
|
@@ -148,6 +149,9 @@ files:
|
|
148
149
|
- ./Rakefile
|
149
150
|
- ./README.md
|
150
151
|
- ./resources/banner.png
|
152
|
+
- ./resources/capture.js
|
153
|
+
- ./resources/ui-screen-shooter.sh
|
154
|
+
- ./resources/unix_instruments.sh
|
151
155
|
- bin/longbow
|
152
156
|
homepage: https://github.com/intermark/longbow
|
153
157
|
licenses:
|