longbow-fdv 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,121 @@
1
+ require 'xcodeproj'
2
+ require 'colors'
3
+ require 'plist'
4
+ require 'utilities'
5
+
6
+ module Longbow
7
+
8
+ def self.update_target directory, target, global_keys, info_keys, icon, launch
9
+ unless directory && target
10
+ Longbow::red ' Invalid parameters. Could not create/update target named: ' + target
11
+ return false
12
+ end
13
+
14
+ # Find Project File
15
+ project_paths = []
16
+ Dir.foreach(directory) do |fname|
17
+ project_paths << fname if fname.include? '.xcodeproj'
18
+ end
19
+
20
+ # Open The Project
21
+ return false if project_paths.length == 0
22
+ proj = Xcodeproj::Project.open(project_paths[0])
23
+
24
+ # Get Main Target's Basic Info
25
+ @target = nil
26
+ proj.targets.each do |t|
27
+ if t.to_s == target
28
+ @target = t
29
+ Longbow::blue ' ' + target + ' found.' unless $nolog
30
+ break
31
+ end
32
+ end
33
+
34
+ #puts proj.pretty_print
35
+
36
+ # Create Target if Necessary
37
+ main_target = proj.targets.first
38
+ @target = create_target(proj, target) unless @target
39
+
40
+ # Plist Creating/Adding
41
+ main_plist = main_target.build_configurations[0].build_settings['INFOPLIST_FILE']
42
+
43
+ main_plist.sub! '$(SRCROOT)/', ''
44
+ main_plist_contents = File.read(directory + '/' + main_plist)
45
+ target_plist_path = directory + '/' + main_plist.split('/')[0] + '/' + target + '-info.plist'
46
+ plist_text = Longbow::create_plist_from_old_plist main_plist_contents, info_keys, global_keys
47
+ File.open(target_plist_path, 'w') do |f|
48
+ f.write(plist_text)
49
+ end
50
+ Longbow::green ' - ' + target + '-info.plist Updated.' unless $nolog
51
+
52
+ # Add Build Settings
53
+ @target.build_configurations.each do |b|
54
+ # Main Settings
55
+ main_settings = nil
56
+ base_config = nil
57
+ main_target.build_configurations.each do |bc|
58
+ main_settings = bc.build_settings if bc.to_s == b.to_s
59
+ base_config = bc.base_configuration_reference if bc.to_s == b.to_s
60
+ end
61
+ settings = b.build_settings
62
+
63
+ if main_settings
64
+ main_settings.each_key do |key|
65
+ settings[key] = main_settings[key]
66
+ end
67
+ end
68
+ # Plist & Icons
69
+ settings['INFOPLIST_FILE'] = main_plist.split('/')[0] + '/' + target + '-info.plist'
70
+ settings['ASSETCATALOG_COMPILER_APPICON_NAME'] = Longbow::stripped_text(target) if icon
71
+ settings['ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME'] = Longbow::stripped_text(target) if launch
72
+ settings['SKIP_INSTALL'] = 'NO'
73
+
74
+ if File.exists? directory + '/Pods'
75
+ b.base_configuration_reference = base_config
76
+ settings['PODS_ROOT'] = '${SRCROOT}/Pods'
77
+ end
78
+ end
79
+
80
+ # Save The Project
81
+ proj.save
82
+ end
83
+
84
+ def self.create_target project, target
85
+ main_target = project.targets.first
86
+ deployment_target = main_target.deployment_target
87
+
88
+ # Create New Target
89
+ new_target = Xcodeproj::Project::ProjectHelper.new_target project, :application, target, :ios, deployment_target, project.products_group, 'en'
90
+ if new_target
91
+ # Add Build Phases
92
+ main_target.build_phases.objects.each do |b|
93
+ if b.isa == 'PBXSourcesBuildPhase'
94
+ b.files_references.each do |f|
95
+ new_target.source_build_phase.add_file_reference f
96
+ end
97
+ elsif b.isa == 'PBXFrameworksBuildPhase'
98
+ b.files_references.each do |f|
99
+ new_target.frameworks_build_phase.add_file_reference f
100
+ end
101
+ elsif b.isa == 'PBXResourcesBuildPhase'
102
+ b.files_references.each do |f|
103
+ new_target.resources_build_phase.add_file_reference f
104
+ end
105
+ elsif b.isa == 'PBXShellScriptBuildPhase'
106
+ phase = new_target.new_shell_script_build_phase(name = b.display_name)
107
+ phase.shell_script = b.shell_script
108
+ end
109
+ end
110
+
111
+ Longbow::blue ' ' + target + ' created.' unless $nolog
112
+ else
113
+ puts
114
+ Longbow::red ' Target Creation failed for target named: ' + target
115
+ puts
116
+ end
117
+
118
+ return new_target
119
+ end
120
+
121
+ end
@@ -0,0 +1,8 @@
1
+ $:.push File.expand_path('../', __FILE__)
2
+
3
+ module Longbow
4
+ # Strip Non-Alphanumerics
5
+ def self.stripped_text text
6
+ return text.gsub(/[^0-9a-z ]/i, '')
7
+ end
8
+ end
@@ -0,0 +1,12 @@
1
+ $:.push File.expand_path('../', __FILE__)
2
+ require 'colors'
3
+
4
+ module Longbow
5
+ VERSION = '0.1.0'
6
+
7
+ def self.check_for_newer_version
8
+ unless Gem.latest_version_for('longbow').to_s == VERSION
9
+ Longbow::purple "\n A newer version of longbow is available. Run '[sudo] gem update longbow'."
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,31 @@
1
+ #!/bin/bash
2
+ set -e # Bomb on any script errors
3
+ target_string="$1"
4
+ verbose=false
5
+ if [ -n "$2" ]; then
6
+ verbose=true
7
+ fi
8
+
9
+ function main {
10
+ # Get targets into an array, run 'em
11
+ IFS=',' read -a targets <<< "$target_string"
12
+ for target in "${targets[@]}"; do
13
+ _run_target $target;
14
+ done
15
+ # Remove files added by ruby script
16
+ rm "capture.js"
17
+ rm "config-screenshots.sh"
18
+ rm "ui-screen-shooter.sh"
19
+ rm "unix_instruments.sh"
20
+ }
21
+
22
+ function _run_target {
23
+ echo " Running $1"
24
+ if [ "$verbose" = true ]; then
25
+ source ui-screen-shooter.sh "$HOME/Desktop/screenshots/$1" "$1"
26
+ else
27
+ source ui-screen-shooter.sh "$HOME/Desktop/screenshots/$1" "$1" >/dev/null 2>/dev/null
28
+ fi
29
+ }
30
+
31
+ main
Binary file
@@ -0,0 +1,84 @@
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
+ var kPortraitString = "portrait"
22
+ var kLandscapeString = "landscape"
23
+
24
+ var kMaxDimension4inch = 568;
25
+ var kMaxDimension4point7inch = 667;
26
+ var kMaxDimension5point5inch = 736;
27
+
28
+ // rectMaxSizeMatchesPhoneWithMaxDimensionForOrientation(rect, maxDimension, orientation)
29
+ //
30
+ // Returns whether the given rect matches a given max dimension in a particular orientation.
31
+ //
32
+ // `rect` is the rectangle representing the image size you want to check
33
+ // `maxDimension` is the size of the longest side of the screen on a given device
34
+ // `orientation` is...well...duh!
35
+ //
36
+ function rectMaxSizeMatchesPhoneWithMaxDimensionForOrientation(rect, maxDimension, orientation) {
37
+ return (orientation == kPortraitString && rect.size.height == maxDimension) || (orientation == kLandscapeString && rect.size.width == maxDimension)
38
+ }
39
+
40
+ // captureLocalizedScreenshot(name)
41
+ //
42
+ // Tells the local target to take a screen shot and names the file after the
43
+ // state of the simulator like so:
44
+ //
45
+ // [model]___[orientation]___[name].png
46
+ //
47
+ // `model` is the model of the device (iphone, iphone5, ipad)
48
+ // `orientation` is...well...duh!
49
+ // `name` is what you passed in to the function
50
+ //
51
+ // Screenshots are saved along with the trace results in UI Automation. See
52
+ // `run_screenshooter.sh` for examples on how to pull those images out and put
53
+ // them wherever you want.
54
+ //
55
+ function captureLocalizedScreenshot(name) {
56
+ var target = UIATarget.localTarget();
57
+ var model = target.model();
58
+ var rect = target.rect();
59
+
60
+ var orientation = kPortraitString;
61
+ if (rect.size.height < rect.size.width) {
62
+ orientation = kLandscapeString;
63
+ }
64
+
65
+ if (model.match(/iPhone/)) {
66
+ if (rectMaxSizeMatchesPhoneWithMaxDimensionForOrientation(rect, kMaxDimension4inch, orientation)) {
67
+ model = "iOS-4-in";
68
+ }
69
+ else if (rectMaxSizeMatchesPhoneWithMaxDimensionForOrientation(rect, kMaxDimension4point7inch, orientation)) {
70
+ model = "iOS-4.7-in";
71
+ }
72
+ else if (rectMaxSizeMatchesPhoneWithMaxDimensionForOrientation(rect, kMaxDimension5point5inch, orientation)) {
73
+ model = "iOS-5.5-in";
74
+ }
75
+ else {
76
+ model = "iOS-3.5-in";
77
+ }
78
+ } else {
79
+ model = "iOS-iPad";
80
+ }
81
+
82
+ var parts = [model, orientation, name];
83
+ target.captureScreenWithName(parts.join("___"));
84
+ }
@@ -0,0 +1,28 @@
1
+ #!/bin/bash
2
+ # This is an example configuration file to be used with ui-screen-shooter
3
+ # It is designed to work with the Hello World International application
4
+ # Please copy to config-screenshots.sh and edit for your needs
5
+
6
+
7
+ # LOCALE
8
+ # ======
9
+ # Set the locales here in which your screenshots should be made.
10
+ # Use format like en-US zh-Hans for filenames compatible with iTMSTransporter
11
+ # Note: to get the locale names for your existing app:
12
+ # - Download .itmsp file with iTMSTransporter
13
+ # - Run `grep locale ~/Desktop/*.itmsp/metadata.xml | grep name | sort -u`
14
+
15
+ export languages="en-US"
16
+
17
+
18
+ # SIMULATORS
19
+ # ==========
20
+ # The simulators we want to run the script against, declared as a Bash array.
21
+ # Run `instruments -s devices` to get a list of all the possible string values.
22
+
23
+ declare -xa simulators=(
24
+ "iPhone 6 (8.1 Simulator)",
25
+ "iPhone 6 Plus (8.1 Simulator)",
26
+ "iPhone 5S (8.1 Simulator)",
27
+ "iPhone 4S (8.1 Simulator)"
28
+ )
@@ -0,0 +1,206 @@
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
+ function main {
32
+ # Load configuration
33
+ # Not in a separate function because you can't exort arrays
34
+ # https://stackoverflow.com/questions/5564418/exporting-an-array-in-bash-script
35
+ # Will export languages and simulators bash variables
36
+ export UISS_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
37
+ if [ -f "$UISS_DIR"/config-screenshots.sh ]; then
38
+ source "$UISS_DIR"/config-screenshots.sh
39
+ else
40
+ if [ -f "$UISS_DIR"/config-screenshots.example.sh ]; then
41
+ source "$UISS_DIR"/config-screenshots.example.sh
42
+ echo "WARNING: Using example config-screenshots file, you should create your own"
43
+ else
44
+ echo "Configuration \"config-screenshots.sh\" does not exist! Aborting."
45
+ exit 1
46
+ fi
47
+ fi
48
+
49
+ _check_destination
50
+ _check_ui_script
51
+ _check_scheme_name
52
+ _xcode clean build
53
+
54
+ for simulator in "${simulators[@]}"; do
55
+ for language in $languages; do
56
+ _clean_trace_results_dir
57
+ _run_automation "$ui_script" "$language" "$simulator"
58
+ _copy_screenshots "$language"
59
+ done
60
+ done
61
+
62
+ _close_sim
63
+
64
+ echo
65
+ echo "Screenshots complete!"
66
+ }
67
+
68
+ # Global variables to keep track of where everything goes
69
+ tmp_dir="/tmp"
70
+ build_dir="$tmp_dir/screen_shooter"
71
+ bundle_dir="$build_dir/app.app"
72
+ trace_results_dir="$build_dir/traces"
73
+
74
+ function _check_destination {
75
+ # Abort if the destination directory already exists. Better safe than sorry.
76
+
77
+ if [ -z "$destination" ]; then
78
+ destination="$HOME/Desktop/screenshots"
79
+ fi
80
+ if [ -d "$destination" ]; then
81
+ echo "Destination directory \"$destination\" already exists! Moving Directory."
82
+ mv "$destination" "$HOME/Desktop/screenshots$(date +"%Y%m%d%H%M")"
83
+ fi
84
+ }
85
+
86
+ function _check_ui_script {
87
+ # Abort if the UI script does not exist.
88
+
89
+ if [ -z "$ui_script" ]; then
90
+ ui_script="./config-automation.js"
91
+ fi
92
+ if [ ! -f "$ui_script" ]; then
93
+ if [ -f "./config-automation.example.js" ]; then
94
+ ui_script="./config-automation.js"
95
+ echo "WARNING: Using example config-automation, please create your own"
96
+ else
97
+ echo "Config-automation does not exist! Aborting."
98
+ exit 1
99
+ fi
100
+ fi
101
+ }
102
+
103
+ function _check_scheme_name {
104
+ if [ -z "$scheme_name" ]; then
105
+ scheme_name=$(basename *.xcworkspace .xcworkspace)
106
+ echo "No scheme name specified, using the default."
107
+ fi
108
+ }
109
+
110
+ function _xcode {
111
+ # A wrapper around `xcodebuild` that tells it to build the app in the temp
112
+ # directory. If your app uses workspaces or special schemes, you'll need to
113
+ # specify them here.
114
+ #
115
+ # Use `man xcodebuild` for more information on how to build your project.
116
+ if test -n "$(find . -maxdepth 1 -name '*.xcworkspace' -print -quit)"
117
+ then
118
+ base=$(basename *.xcworkspace .xcworkspace)
119
+ # First build omits PRODUCT_NAME
120
+ # Do NOT ask me why you need to build this twice for it to work
121
+ # or how I became to know this fact
122
+ xcodebuild -sdk "iphonesimulator$ios_version" \
123
+ CONFIGURATION_BUILD_DIR="$build_dir/build" \
124
+ -workspace "$base.xcworkspace" -scheme "$scheme_name" -configuration Debug \
125
+ PRODUCT_NAME="$scheme_name" \
126
+ DSTROOT=$build_dir \
127
+ OBJROOT=$build_dir \
128
+ SYMROOT=$build_dir \
129
+ ONLY_ACTIVE_ARCH=NO \
130
+ "$@"
131
+ xcodebuild -sdk "iphonesimulator$ios_version" \
132
+ CONFIGURATION_BUILD_DIR="$build_dir/build" \
133
+ -workspace "$base.xcworkspace" -scheme "$scheme_name" -configuration Debug \
134
+ PRODUCT_NAME="$scheme_name" \
135
+ DSTROOT=$build_dir \
136
+ OBJROOT=$build_dir \
137
+ SYMROOT=$build_dir \
138
+ ONLY_ACTIVE_ARCH=NO \
139
+ "$@"
140
+ cp -r "$build_dir/build/$scheme_name.app" "$build_dir"
141
+ bundle_dir="$build_dir/$scheme_name.app"
142
+ else
143
+ xcodebuild -sdk "iphonesimulator$ios_version" \
144
+ CONFIGURATION_BUILD_DIR=$build_dir \
145
+ PRODUCT_NAME=app \
146
+ "$@"
147
+ fi
148
+ }
149
+
150
+ function _clean_trace_results_dir {
151
+ # Removes the trace results directory. We need to do this because Instruments
152
+ # keeps appending new trace runs and it's simpler for us to always assume
153
+ # there's just one run recorded where we look for screenshots.
154
+
155
+ rm -rf "$trace_results_dir"
156
+ mkdir -p "$trace_results_dir"
157
+ }
158
+
159
+ function _run_automation {
160
+ # Runs the UI Automation JavaScript file that actually takes the screenshots.
161
+
162
+ automation_script="$1"
163
+ language="$2"
164
+ simulator="$3"
165
+
166
+ echo "Running automation script \"$automation_script\"
167
+ for \"$simulator\"
168
+ in language \"${language}\"..."
169
+
170
+ dev_tools_dir=`xcode-select -print-path`
171
+ tracetemplate="Automation"
172
+
173
+ # Check out the `unix_instruments.sh` script to see why we need this wrapper.
174
+ DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
175
+ "$DIR"/unix_instruments.sh \
176
+ -w "$simulator" \
177
+ -D "$trace_results_dir/trace" \
178
+ -t "$tracetemplate" \
179
+ "$bundle_dir" \
180
+ -e UIARESULTSPATH "$trace_results_dir" \
181
+ -e UIASCRIPT "$automation_script" \
182
+ -AppleLanguages "($language)" \
183
+ -AppleLocale "$language"
184
+
185
+ find $trace_results_dir/Run\ 1/ -name *landscape*png -type f -exec sips -r -90 \{\} \;
186
+ }
187
+
188
+ function _copy_screenshots {
189
+ # Since we're always clearing out the trace results before every run, we can
190
+ # assume that any screenshots were saved in the "Run 1" directory. Copy them
191
+ # to the destination's language folder!
192
+
193
+ language="$1"
194
+
195
+ mkdir -p "$destination/$language"
196
+ cp $trace_results_dir/Run\ 1/*.png "$destination/$language"
197
+ }
198
+
199
+ function _close_sim {
200
+ # I know, I know. It says "iPhone Simulator". For some reason,
201
+ # that's the only way Applescript can identify it.
202
+ osascript -e "tell application \"iPhone Simulator\" to quit"
203
+ }
204
+
205
+ main
206
+