xcres 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +33 -0
- data/.travis.yml +18 -0
- data/Gemfile +8 -0
- data/Gemfile.lock +85 -0
- data/LICENSE.txt +22 -0
- data/README.md +181 -0
- data/Rakefile +58 -0
- data/bin/xcres +12 -0
- data/lib/xcres/analyzer/aggregate_analyzer.rb +48 -0
- data/lib/xcres/analyzer/analyzer.rb +141 -0
- data/lib/xcres/analyzer/resources_aggregate_analyzer.rb +27 -0
- data/lib/xcres/analyzer/resources_analyzer/base_resources_analyzer.rb +133 -0
- data/lib/xcres/analyzer/resources_analyzer/bundle_resources_analyzer.rb +68 -0
- data/lib/xcres/analyzer/resources_analyzer/loose_resources_analyzer.rb +39 -0
- data/lib/xcres/analyzer/resources_analyzer/xcassets_analyzer.rb +62 -0
- data/lib/xcres/analyzer/strings_analyzer.rb +255 -0
- data/lib/xcres/builder/file_builder.rb +61 -0
- data/lib/xcres/builder/resources_builder.rb +184 -0
- data/lib/xcres/builder/string_builder.rb +31 -0
- data/lib/xcres/command/build_command.rb +83 -0
- data/lib/xcres/command/command.rb +58 -0
- data/lib/xcres/command/install_command.rb +173 -0
- data/lib/xcres/command/main_command.rb +14 -0
- data/lib/xcres/command/project_command.rb +111 -0
- data/lib/xcres/command/version_command.rb +12 -0
- data/lib/xcres/helper/file_helper.rb +16 -0
- data/lib/xcres/logger.rb +148 -0
- data/lib/xcres/model/section.rb +43 -0
- data/lib/xcres/model/xcassets/bundle.rb +55 -0
- data/lib/xcres/model/xcassets/resource.rb +141 -0
- data/lib/xcres/model/xcassets/resource_image.rb +134 -0
- data/lib/xcres/version.rb +9 -0
- data/lib/xcres.rb +9 -0
- data/spec/fixtures/Example/Example/AppDelegate.h +15 -0
- data/spec/fixtures/Example/Example/AppDelegate.m +49 -0
- data/spec/fixtures/Example/Example/Example-Info.plist +38 -0
- data/spec/fixtures/Example/Example/Example-Prefix.pch +16 -0
- data/spec/fixtures/Example/Example/Images/doge.jpeg +0 -0
- data/spec/fixtures/Example/Example/Images/nyanCat.png +0 -0
- data/spec/fixtures/Example/Example/Images.xcassets/AppIcon.appiconset/Contents.json +23 -0
- data/spec/fixtures/Example/Example/Images.xcassets/Doge.imageset/Contents.json +18 -0
- data/spec/fixtures/Example/Example/Images.xcassets/Doge.imageset/doge.png +0 -0
- data/spec/fixtures/Example/Example/Images.xcassets/Doge.imageset/doge@2x.png +0 -0
- data/spec/fixtures/Example/Example/Images.xcassets/LaunchImage.launchimage/Contents.json +23 -0
- data/spec/fixtures/Example/Example/de.lproj/Localizable.strings +12 -0
- data/spec/fixtures/Example/Example/en.lproj/InfoPlist.strings +2 -0
- data/spec/fixtures/Example/Example/en.lproj/Localizable.strings +15 -0
- data/spec/fixtures/Example/Example/main.m +18 -0
- data/spec/fixtures/Example/Example.xcodeproj/project.pbxproj +449 -0
- data/spec/fixtures/Example/Example.xcodeproj/project.xcworkspace/contents.xcworkspacedata +7 -0
- data/spec/fixtures/ExampleOSX/ExampleOSX/AppDelegate.h +15 -0
- data/spec/fixtures/ExampleOSX/ExampleOSX/AppDelegate.m +18 -0
- data/spec/fixtures/ExampleOSX/ExampleOSX/Base.lproj/MainMenu.xib +680 -0
- data/spec/fixtures/ExampleOSX/ExampleOSX/ExampleOSX-Info.plist +34 -0
- data/spec/fixtures/ExampleOSX/ExampleOSX/ExampleOSX-Prefix.pch +9 -0
- data/spec/fixtures/ExampleOSX/ExampleOSX/Images.xcassets/AppIcon.appiconset/Contents.json +58 -0
- data/spec/fixtures/ExampleOSX/ExampleOSX/en.lproj/Credits.rtf +29 -0
- data/spec/fixtures/ExampleOSX/ExampleOSX/en.lproj/InfoPlist.strings +2 -0
- data/spec/fixtures/ExampleOSX/ExampleOSX/main.m +14 -0
- data/spec/fixtures/ExampleOSX/ExampleOSX.xcodeproj/project.pbxproj +481 -0
- data/spec/fixtures/ExampleOSX/ExampleOSX.xcodeproj/project.xcworkspace/contents.xcworkspacedata +7 -0
- data/spec/fixtures/ExampleOSX/ExampleOSXTests/ExampleOSXTests-Info.plist +22 -0
- data/spec/fixtures/ExampleOSX/ExampleOSXTests/ExampleOSXTests.m +34 -0
- data/spec/fixtures/ExampleOSX/ExampleOSXTests/en.lproj/InfoPlist.strings +2 -0
- data/spec/integration/build/after/Example/Example/AppDelegate.h +15 -0
- data/spec/integration/build/after/Example/Example/AppDelegate.m +49 -0
- data/spec/integration/build/after/Example/Example/Example-Info.plist +38 -0
- data/spec/integration/build/after/Example/Example/Example-Prefix.pch +16 -0
- data/spec/integration/build/after/Example/Example/Icons.bundle/tab_bar/tabbar_list.png +0 -0
- data/spec/integration/build/after/Example/Example/Icons.bundle/tab_bar/tabbar_list@2x.png +0 -0
- data/spec/integration/build/after/Example/Example/Icons.bundle/tab_bar/tabbar_map.png +0 -0
- data/spec/integration/build/after/Example/Example/Icons.bundle/tab_bar/tabbar_map@2x.png +0 -0
- data/spec/integration/build/after/Example/Example/Images/doge.jpeg +0 -0
- data/spec/integration/build/after/Example/Example/Images/nyanCat.png +0 -0
- data/spec/integration/build/after/Example/Example/Images.xcassets/AppIcon.appiconset/Contents.json +23 -0
- data/spec/integration/build/after/Example/Example/Images.xcassets/Doge.imageset/Contents.json +18 -0
- data/spec/integration/build/after/Example/Example/Images.xcassets/Doge.imageset/doge.png +0 -0
- data/spec/integration/build/after/Example/Example/Images.xcassets/Doge.imageset/doge@2x.png +0 -0
- data/spec/integration/build/after/Example/Example/Images.xcassets/LaunchImage.launchimage/Contents.json +23 -0
- data/spec/integration/build/after/Example/Example/de.lproj/Localizable.strings +12 -0
- data/spec/integration/build/after/Example/Example/en.lproj/InfoPlist.strings +2 -0
- data/spec/integration/build/after/Example/Example/en.lproj/Localizable.strings +15 -0
- data/spec/integration/build/after/Example/Example/main.m +18 -0
- data/spec/integration/build/after/Example/Example.xcodeproj.yaml +168 -0
- data/spec/integration/build/after/R.h +39 -0
- data/spec/integration/build/after/R.m +29 -0
- data/spec/integration/build/after/execution_output.txt +19 -0
- data/spec/integration/build/before/Example/Example/AppDelegate.h +15 -0
- data/spec/integration/build/before/Example/Example/AppDelegate.m +49 -0
- data/spec/integration/build/before/Example/Example/Example-Info.plist +38 -0
- data/spec/integration/build/before/Example/Example/Example-Prefix.pch +16 -0
- data/spec/integration/build/before/Example/Example/Icons.bundle/tab_bar/tabbar_list.png +0 -0
- data/spec/integration/build/before/Example/Example/Icons.bundle/tab_bar/tabbar_list@2x.png +0 -0
- data/spec/integration/build/before/Example/Example/Icons.bundle/tab_bar/tabbar_map.png +0 -0
- data/spec/integration/build/before/Example/Example/Icons.bundle/tab_bar/tabbar_map@2x.png +0 -0
- data/spec/integration/build/before/Example/Example/Images/doge.jpeg +0 -0
- data/spec/integration/build/before/Example/Example/Images/nyanCat.png +0 -0
- data/spec/integration/build/before/Example/Example/Images.xcassets/AppIcon.appiconset/Contents.json +23 -0
- data/spec/integration/build/before/Example/Example/Images.xcassets/Doge.imageset/Contents.json +18 -0
- data/spec/integration/build/before/Example/Example/Images.xcassets/Doge.imageset/doge.png +0 -0
- data/spec/integration/build/before/Example/Example/Images.xcassets/Doge.imageset/doge@2x.png +0 -0
- data/spec/integration/build/before/Example/Example/Images.xcassets/LaunchImage.launchimage/Contents.json +23 -0
- data/spec/integration/build/before/Example/Example/de.lproj/Localizable.strings +12 -0
- data/spec/integration/build/before/Example/Example/en.lproj/InfoPlist.strings +2 -0
- data/spec/integration/build/before/Example/Example/en.lproj/Localizable.strings +15 -0
- data/spec/integration/build/before/Example/Example/main.m +18 -0
- data/spec/integration/build/before/Example/Example.xcodeproj/project.pbxproj +453 -0
- data/spec/integration/build/before/Example/Example.xcodeproj/project.xcworkspace/contents.xcworkspacedata +7 -0
- data/spec/integration/build-keyword-clash/after/Example/Example/AppDelegate.h +15 -0
- data/spec/integration/build-keyword-clash/after/Example/Example/AppDelegate.m +49 -0
- data/spec/integration/build-keyword-clash/after/Example/Example/Default-568h@2x.png +0 -0
- data/spec/integration/build-keyword-clash/after/Example/Example/Default.png +0 -0
- data/spec/integration/build-keyword-clash/after/Example/Example/Default@2x.png +0 -0
- data/spec/integration/build-keyword-clash/after/Example/Example/Example-Info.plist +38 -0
- data/spec/integration/build-keyword-clash/after/Example/Example/Example-Prefix.pch +16 -0
- data/spec/integration/build-keyword-clash/after/Example/Example/Images.xcassets/AppIcon.appiconset/Contents.json +23 -0
- data/spec/integration/build-keyword-clash/after/Example/Example/en.lproj/InfoPlist.strings +2 -0
- data/spec/integration/build-keyword-clash/after/Example/Example/main.m +18 -0
- data/spec/integration/build-keyword-clash/after/Example/Example.xcodeproj.yaml +160 -0
- data/spec/integration/build-keyword-clash/after/R.h +15 -0
- data/spec/integration/build-keyword-clash/after/R.m +15 -0
- data/spec/integration/build-keyword-clash/after/execution_output.txt +14 -0
- data/spec/integration/build-keyword-clash/before/Example/Example/AppDelegate.h +15 -0
- data/spec/integration/build-keyword-clash/before/Example/Example/AppDelegate.m +49 -0
- data/spec/integration/build-keyword-clash/before/Example/Example/Default-568h@2x.png +0 -0
- data/spec/integration/build-keyword-clash/before/Example/Example/Default.png +0 -0
- data/spec/integration/build-keyword-clash/before/Example/Example/Default@2x.png +0 -0
- data/spec/integration/build-keyword-clash/before/Example/Example/Example-Info.plist +38 -0
- data/spec/integration/build-keyword-clash/before/Example/Example/Example-Prefix.pch +16 -0
- data/spec/integration/build-keyword-clash/before/Example/Example/Images.xcassets/AppIcon.appiconset/Contents.json +23 -0
- data/spec/integration/build-keyword-clash/before/Example/Example/en.lproj/InfoPlist.strings +2 -0
- data/spec/integration/build-keyword-clash/before/Example/Example/main.m +18 -0
- data/spec/integration/build-keyword-clash/before/Example/Example.xcodeproj/project.pbxproj +427 -0
- data/spec/integration/build-keyword-clash/before/Example/Example.xcodeproj/project.xcworkspace/contents.xcworkspacedata +7 -0
- data/spec/integration/build-var-infoplist/after/Example/Example/AppDelegate.h +15 -0
- data/spec/integration/build-var-infoplist/after/Example/Example/AppDelegate.m +49 -0
- data/spec/integration/build-var-infoplist/after/Example/Example/Example-Info.plist +38 -0
- data/spec/integration/build-var-infoplist/after/Example/Example/Example-Prefix.pch +16 -0
- data/spec/integration/build-var-infoplist/after/Example/Example/Icons.bundle/tab_bar/tabbar_list.png +0 -0
- data/spec/integration/build-var-infoplist/after/Example/Example/Icons.bundle/tab_bar/tabbar_list@2x.png +0 -0
- data/spec/integration/build-var-infoplist/after/Example/Example/Icons.bundle/tab_bar/tabbar_map.png +0 -0
- data/spec/integration/build-var-infoplist/after/Example/Example/Icons.bundle/tab_bar/tabbar_map@2x.png +0 -0
- data/spec/integration/build-var-infoplist/after/Example/Example/Images/doge.jpeg +0 -0
- data/spec/integration/build-var-infoplist/after/Example/Example/Images/nyanCat.png +0 -0
- data/spec/integration/build-var-infoplist/after/Example/Example/Images.xcassets/AppIcon.appiconset/Contents.json +23 -0
- data/spec/integration/build-var-infoplist/after/Example/Example/Images.xcassets/Doge.imageset/Contents.json +18 -0
- data/spec/integration/build-var-infoplist/after/Example/Example/Images.xcassets/Doge.imageset/doge.png +0 -0
- data/spec/integration/build-var-infoplist/after/Example/Example/Images.xcassets/Doge.imageset/doge@2x.png +0 -0
- data/spec/integration/build-var-infoplist/after/Example/Example/Images.xcassets/LaunchImage.launchimage/Contents.json +23 -0
- data/spec/integration/build-var-infoplist/after/Example/Example/de.lproj/Localizable.strings +12 -0
- data/spec/integration/build-var-infoplist/after/Example/Example/en.lproj/InfoPlist.strings +2 -0
- data/spec/integration/build-var-infoplist/after/Example/Example/en.lproj/Localizable.strings +15 -0
- data/spec/integration/build-var-infoplist/after/Example/Example/main.m +18 -0
- data/spec/integration/build-var-infoplist/after/Example/Example.xcodeproj.yaml +168 -0
- data/spec/integration/build-var-infoplist/after/R.h +39 -0
- data/spec/integration/build-var-infoplist/after/R.m +29 -0
- data/spec/integration/build-var-infoplist/after/execution_output.txt +19 -0
- data/spec/integration/build-var-infoplist/before/Example/Example/AppDelegate.h +15 -0
- data/spec/integration/build-var-infoplist/before/Example/Example/AppDelegate.m +49 -0
- data/spec/integration/build-var-infoplist/before/Example/Example/Example-Info.plist +38 -0
- data/spec/integration/build-var-infoplist/before/Example/Example/Example-Prefix.pch +16 -0
- data/spec/integration/build-var-infoplist/before/Example/Example/Icons.bundle/tab_bar/tabbar_list.png +0 -0
- data/spec/integration/build-var-infoplist/before/Example/Example/Icons.bundle/tab_bar/tabbar_list@2x.png +0 -0
- data/spec/integration/build-var-infoplist/before/Example/Example/Icons.bundle/tab_bar/tabbar_map.png +0 -0
- data/spec/integration/build-var-infoplist/before/Example/Example/Icons.bundle/tab_bar/tabbar_map@2x.png +0 -0
- data/spec/integration/build-var-infoplist/before/Example/Example/Images/doge.jpeg +0 -0
- data/spec/integration/build-var-infoplist/before/Example/Example/Images/nyanCat.png +0 -0
- data/spec/integration/build-var-infoplist/before/Example/Example/Images.xcassets/AppIcon.appiconset/Contents.json +23 -0
- data/spec/integration/build-var-infoplist/before/Example/Example/Images.xcassets/Doge.imageset/Contents.json +18 -0
- data/spec/integration/build-var-infoplist/before/Example/Example/Images.xcassets/Doge.imageset/doge.png +0 -0
- data/spec/integration/build-var-infoplist/before/Example/Example/Images.xcassets/Doge.imageset/doge@2x.png +0 -0
- data/spec/integration/build-var-infoplist/before/Example/Example/Images.xcassets/LaunchImage.launchimage/Contents.json +23 -0
- data/spec/integration/build-var-infoplist/before/Example/Example/de.lproj/Localizable.strings +12 -0
- data/spec/integration/build-var-infoplist/before/Example/Example/en.lproj/InfoPlist.strings +2 -0
- data/spec/integration/build-var-infoplist/before/Example/Example/en.lproj/Localizable.strings +15 -0
- data/spec/integration/build-var-infoplist/before/Example/Example/main.m +18 -0
- data/spec/integration/build-var-infoplist/before/Example/Example.xcodeproj/project.pbxproj +453 -0
- data/spec/integration/build-var-infoplist/before/Example/Example.xcodeproj/project.xcworkspace/contents.xcworkspacedata +7 -0
- data/spec/integration/help/after/execution_output.txt +18 -0
- data/spec/integration/help/before/.gitkeep +0 -0
- data/spec/integration/install/after/Example/Example/AppDelegate.h +15 -0
- data/spec/integration/install/after/Example/Example/AppDelegate.m +49 -0
- data/spec/integration/install/after/Example/Example/Example-Info.plist +38 -0
- data/spec/integration/install/after/Example/Example/Example-Prefix.pch +18 -0
- data/spec/integration/install/after/Example/Example/Images.xcassets/AppIcon.appiconset/Contents.json +23 -0
- data/spec/integration/install/after/Example/Example/Images.xcassets/LaunchImage.launchimage/Contents.json +23 -0
- data/spec/integration/install/after/Example/Example/Resources/R.h +19 -0
- data/spec/integration/install/after/Example/Example/Resources/R.m +17 -0
- data/spec/integration/install/after/Example/Example/en.lproj/InfoPlist.strings +2 -0
- data/spec/integration/install/after/Example/Example/main.m +18 -0
- data/spec/integration/install/after/Example/Example.xcodeproj/project.pbxproj +898 -0
- data/spec/integration/install/after/Example/Example.xcodeproj/project.xcworkspace/contents.xcworkspacedata +7 -0
- data/spec/integration/install/after/Example/Example.xcodeproj.yaml +172 -0
- data/spec/integration/install/after/execution_output.txt +22 -0
- data/spec/integration/install/before/Example/Example/AppDelegate.h +15 -0
- data/spec/integration/install/before/Example/Example/AppDelegate.m +49 -0
- data/spec/integration/install/before/Example/Example/Example-Info.plist +38 -0
- data/spec/integration/install/before/Example/Example/Example-Prefix.pch +16 -0
- data/spec/integration/install/before/Example/Example/Images.xcassets/AppIcon.appiconset/Contents.json +23 -0
- data/spec/integration/install/before/Example/Example/Images.xcassets/LaunchImage.launchimage/Contents.json +23 -0
- data/spec/integration/install/before/Example/Example/en.lproj/InfoPlist.strings +2 -0
- data/spec/integration/install/before/Example/Example/main.m +18 -0
- data/spec/integration/install/before/Example/Example.xcodeproj/project.pbxproj +421 -0
- data/spec/integration/install/before/Example/Example.xcodeproj/project.xcworkspace/contents.xcworkspacedata +7 -0
- data/spec/integration/install-again/after/Example/Example/AppDelegate.h +15 -0
- data/spec/integration/install-again/after/Example/Example/AppDelegate.m +49 -0
- data/spec/integration/install-again/after/Example/Example/Example-Info.plist +38 -0
- data/spec/integration/install-again/after/Example/Example/Example-Prefix.pch +18 -0
- data/spec/integration/install-again/after/Example/Example/Images.xcassets/AppIcon.appiconset/Contents.json +23 -0
- data/spec/integration/install-again/after/Example/Example/Images.xcassets/LaunchImage.launchimage/Contents.json +23 -0
- data/spec/integration/install-again/after/Example/Example/Resources/R.h +19 -0
- data/spec/integration/install-again/after/Example/Example/Resources/R.m +17 -0
- data/spec/integration/install-again/after/Example/Example/en.lproj/InfoPlist.strings +2 -0
- data/spec/integration/install-again/after/Example/Example/main.m +18 -0
- data/spec/integration/install-again/after/Example/Example.xcodeproj.yaml +172 -0
- data/spec/integration/install-again/after/execution_output.txt +23 -0
- data/spec/integration/install-again/before/Example/Example/AppDelegate.h +15 -0
- data/spec/integration/install-again/before/Example/Example/AppDelegate.m +49 -0
- data/spec/integration/install-again/before/Example/Example/Example-Info.plist +38 -0
- data/spec/integration/install-again/before/Example/Example/Example-Prefix.pch +18 -0
- data/spec/integration/install-again/before/Example/Example/Images.xcassets/AppIcon.appiconset/Contents.json +23 -0
- data/spec/integration/install-again/before/Example/Example/Images.xcassets/LaunchImage.launchimage/Contents.json +23 -0
- data/spec/integration/install-again/before/Example/Example/Resources/R.h +19 -0
- data/spec/integration/install-again/before/Example/Example/Resources/R.m +17 -0
- data/spec/integration/install-again/before/Example/Example/en.lproj/InfoPlist.strings +2 -0
- data/spec/integration/install-again/before/Example/Example/main.m +18 -0
- data/spec/integration/install-again/before/Example/Example.xcodeproj/project.pbxproj +898 -0
- data/spec/integration/install-again/before/Example/Example.xcodeproj/project.xcworkspace/contents.xcworkspacedata +7 -0
- data/spec/integration/install-moved-supporting-files/after/Example/Example.xcodeproj.yaml +173 -0
- data/spec/integration/install-moved-supporting-files/after/Example/Supporting_Files/Example-Info.plist +38 -0
- data/spec/integration/install-moved-supporting-files/after/Example/Supporting_Files/Example-Prefix.pch +18 -0
- data/spec/integration/install-moved-supporting-files/after/Example/Supporting_Files/Resources/R.h +19 -0
- data/spec/integration/install-moved-supporting-files/after/Example/Supporting_Files/Resources/R.m +17 -0
- data/spec/integration/install-moved-supporting-files/after/Example/Supporting_Files/en.lproj/InfoPlist.strings +2 -0
- data/spec/integration/install-moved-supporting-files/after/Example/Supporting_Files/main.m +18 -0
- data/spec/integration/install-moved-supporting-files/after/Example/res/Images.xcassets/AppIcon.appiconset/Contents.json +23 -0
- data/spec/integration/install-moved-supporting-files/after/Example/res/Images.xcassets/LaunchImage.launchimage/Contents.json +23 -0
- data/spec/integration/install-moved-supporting-files/after/Example/src/AppDelegate.h +15 -0
- data/spec/integration/install-moved-supporting-files/after/Example/src/AppDelegate.m +49 -0
- data/spec/integration/install-moved-supporting-files/after/execution_output.txt +22 -0
- data/spec/integration/install-moved-supporting-files/before/Example/Example.xcodeproj/project.pbxproj +431 -0
- data/spec/integration/install-moved-supporting-files/before/Example/Example.xcodeproj/project.xcworkspace/contents.xcworkspacedata +7 -0
- data/spec/integration/install-moved-supporting-files/before/Example/Supporting_Files/Example-Info.plist +38 -0
- data/spec/integration/install-moved-supporting-files/before/Example/Supporting_Files/Example-Prefix.pch +16 -0
- data/spec/integration/install-moved-supporting-files/before/Example/Supporting_Files/en.lproj/InfoPlist.strings +2 -0
- data/spec/integration/install-moved-supporting-files/before/Example/Supporting_Files/main.m +18 -0
- data/spec/integration/install-moved-supporting-files/before/Example/res/Images.xcassets/AppIcon.appiconset/Contents.json +23 -0
- data/spec/integration/install-moved-supporting-files/before/Example/res/Images.xcassets/LaunchImage.launchimage/Contents.json +23 -0
- data/spec/integration/install-moved-supporting-files/before/Example/src/AppDelegate.h +15 -0
- data/spec/integration/install-moved-supporting-files/before/Example/src/AppDelegate.m +49 -0
- data/spec/integration/install-no-supporting-files/after/Example/Example.xcodeproj.yaml +173 -0
- data/spec/integration/install-no-supporting-files/after/Example/Resources/R.h +19 -0
- data/spec/integration/install-no-supporting-files/after/Example/Resources/R.m +17 -0
- data/spec/integration/install-no-supporting-files/after/Example/Supporting_Files/Example-Info.plist +38 -0
- data/spec/integration/install-no-supporting-files/after/Example/Supporting_Files/Example-Prefix.pch +18 -0
- data/spec/integration/install-no-supporting-files/after/Example/Supporting_Files/en.lproj/InfoPlist.strings +2 -0
- data/spec/integration/install-no-supporting-files/after/Example/Supporting_Files/main.m +18 -0
- data/spec/integration/install-no-supporting-files/after/Example/res/Images.xcassets/AppIcon.appiconset/Contents.json +23 -0
- data/spec/integration/install-no-supporting-files/after/Example/res/Images.xcassets/LaunchImage.launchimage/Contents.json +23 -0
- data/spec/integration/install-no-supporting-files/after/Example/src/AppDelegate.h +15 -0
- data/spec/integration/install-no-supporting-files/after/Example/src/AppDelegate.m +49 -0
- data/spec/integration/install-no-supporting-files/after/execution_output.txt +23 -0
- data/spec/integration/install-no-supporting-files/before/Example/Example.xcodeproj/project.pbxproj +430 -0
- data/spec/integration/install-no-supporting-files/before/Example/Example.xcodeproj/project.xcworkspace/contents.xcworkspacedata +7 -0
- data/spec/integration/install-no-supporting-files/before/Example/Supporting_Files/Example-Info.plist +38 -0
- data/spec/integration/install-no-supporting-files/before/Example/Supporting_Files/Example-Prefix.pch +16 -0
- data/spec/integration/install-no-supporting-files/before/Example/Supporting_Files/en.lproj/InfoPlist.strings +2 -0
- data/spec/integration/install-no-supporting-files/before/Example/Supporting_Files/main.m +18 -0
- data/spec/integration/install-no-supporting-files/before/Example/res/Images.xcassets/AppIcon.appiconset/Contents.json +23 -0
- data/spec/integration/install-no-supporting-files/before/Example/res/Images.xcassets/LaunchImage.launchimage/Contents.json +23 -0
- data/spec/integration/install-no-supporting-files/before/Example/src/AppDelegate.h +15 -0
- data/spec/integration/install-no-supporting-files/before/Example/src/AppDelegate.m +49 -0
- data/spec/integration/version/after/execution_output.txt +3 -0
- data/spec/integration/version/before/.gitkeep +0 -0
- data/spec/integration.rb +86 -0
- data/spec/spec_helper/xcodeproj_project_yaml.rb +26 -0
- data/spec/unit/analyzer/aggregate_analyzer_spec.rb +61 -0
- data/spec/unit/analyzer/analyzer_spec.rb +123 -0
- data/spec/unit/analyzer/resources_aggregate_analyzer_spec.rb +46 -0
- data/spec/unit/analyzer/resources_analyzer/base_resources_analyzer_spec.rb +126 -0
- data/spec/unit/analyzer/resources_analyzer/bundle_resources_analyzer_spec.rb +57 -0
- data/spec/unit/analyzer/resources_analyzer/loose_resources_analyzer_spec.rb +22 -0
- data/spec/unit/analyzer/strings_analyzer_spec.rb +99 -0
- data/spec/unit/builder/file_builder_spec.rb +46 -0
- data/spec/unit/builder/resources_builder_spec.rb +50 -0
- data/spec/unit/builder/string_builder_spec.rb +76 -0
- data/spec/unit/command/main_command_spec.rb +5 -0
- data/spec/unit/command/project_command_spec.rb +23 -0
- data/spec/unit/helper/file_helper_spec.rb +24 -0
- data/spec/unit/logger_spec.rb +142 -0
- data/spec/unit/model/section_spec.rb +47 -0
- data/spec/unit/model/xcassets/bundle_spec.rb +154 -0
- data/spec/unit/model/xcassets/resource_image_spec.rb +141 -0
- data/spec/unit/model/xcassets/resource_spec.rb +174 -0
- data/spec/unit/model/xcassets/spec_helper.rb +31 -0
- data/spec/unit/spec_helper.rb +17 -0
- data/xcres.gemspec +42 -0
- metadata +811 -0
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
require 'xcres/builder/file_builder'
|
|
2
|
+
require 'xcres/helper/file_helper'
|
|
3
|
+
|
|
4
|
+
class XCRes::ResourcesBuilder < XCRes::FileBuilder
|
|
5
|
+
|
|
6
|
+
include XCRes::FileHelper
|
|
7
|
+
|
|
8
|
+
BANNER = <<EOS
|
|
9
|
+
// generated by xcres
|
|
10
|
+
//
|
|
11
|
+
// DO NOT EDIT. This file is machine-generated and constantly overwritten.
|
|
12
|
+
// See https://github.com/mrackwitz/xcres for more info.
|
|
13
|
+
//
|
|
14
|
+
EOS
|
|
15
|
+
|
|
16
|
+
COMPILER_KEYWORDS = %w{
|
|
17
|
+
auto break case char const continue default do double else enum extern float
|
|
18
|
+
for goto if inline int long register restrict return short signed sizeof
|
|
19
|
+
static struct switch typedef union unsigned void volatile while
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
# @return [String]
|
|
23
|
+
# the name of the constant in the generated file(s)
|
|
24
|
+
attr_accessor :resources_constant_name
|
|
25
|
+
|
|
26
|
+
# @return [Bool]
|
|
27
|
+
# whether the generated resources constant should contain inline
|
|
28
|
+
# documentation for each key, true by default
|
|
29
|
+
attr_accessor :documented
|
|
30
|
+
alias :documented? :documented
|
|
31
|
+
|
|
32
|
+
# @return [Hash{String => {String => String}}]
|
|
33
|
+
# the sections, which will been written to the built files
|
|
34
|
+
attr_reader :sections
|
|
35
|
+
|
|
36
|
+
# Initialize a new instance
|
|
37
|
+
#
|
|
38
|
+
def initialize
|
|
39
|
+
@sections = {}
|
|
40
|
+
self.documented = true
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Extract resource name from #output_path, if not customized
|
|
44
|
+
#
|
|
45
|
+
# @return [String]
|
|
46
|
+
#
|
|
47
|
+
def resources_constant_name
|
|
48
|
+
@resources_constant_name ||= basename_without_ext output_path
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def add_section name, items, options = {}
|
|
52
|
+
raise ArgumentError.new 'No items given!' if items.nil?
|
|
53
|
+
|
|
54
|
+
transformed_items = {}
|
|
55
|
+
|
|
56
|
+
for key, value in items
|
|
57
|
+
transformed_key = transform_key key, options
|
|
58
|
+
|
|
59
|
+
# Skip invalid key names
|
|
60
|
+
if transformed_key.length == 0
|
|
61
|
+
logger.warn "Skip invalid key: '%s'. (Was transformed to empty text)", key
|
|
62
|
+
next
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# Skip compiler keywords
|
|
66
|
+
if COMPILER_KEYWORDS.include? transformed_key
|
|
67
|
+
logger.warn "Skip invalid key: '%s'. (Was transformed to keyword '%s')", key, transformed_key
|
|
68
|
+
next
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
transformed_items[transformed_key] = value
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
@sections[name] = transformed_items
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def build
|
|
78
|
+
super
|
|
79
|
+
|
|
80
|
+
# Build file contents and write them to disk
|
|
81
|
+
write_file_eventually "#{output_path}.h", (build_contents do |h_file|
|
|
82
|
+
build_header_contents h_file
|
|
83
|
+
end)
|
|
84
|
+
|
|
85
|
+
write_file_eventually "#{output_path}.m", (build_contents do |m_file|
|
|
86
|
+
build_impl_contents m_file
|
|
87
|
+
end)
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
protected
|
|
91
|
+
|
|
92
|
+
def transform_key key, options
|
|
93
|
+
# Split the key into components
|
|
94
|
+
components = key.underscore.split /[_\/ ]/
|
|
95
|
+
|
|
96
|
+
# Build the new key incremental
|
|
97
|
+
result = ''
|
|
98
|
+
|
|
99
|
+
for component in components
|
|
100
|
+
# Ignore empty components
|
|
101
|
+
next unless component.length > 0
|
|
102
|
+
|
|
103
|
+
# Ignore components which are already contained in the key, if enabled
|
|
104
|
+
if options[:shorten_keys]
|
|
105
|
+
next unless result.downcase.scan(component).blank?
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
# Clean component from non alphanumeric characters
|
|
109
|
+
clean_component = component.gsub /[^a-zA-Z0-9]/, ''
|
|
110
|
+
|
|
111
|
+
# Skip if empty
|
|
112
|
+
next unless clean_component.length > 0
|
|
113
|
+
|
|
114
|
+
if result.length == 0
|
|
115
|
+
result += clean_component
|
|
116
|
+
else
|
|
117
|
+
result += clean_component[0].upcase + clean_component[1..-1]
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
result
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def build_header_contents h_file
|
|
125
|
+
h_file.writeln BANNER
|
|
126
|
+
h_file.writeln
|
|
127
|
+
h_file.writeln '#import <Foundation/Foundation.h>'
|
|
128
|
+
h_file.writeln
|
|
129
|
+
h_file.writeln 'extern const struct %s {' % resources_constant_name
|
|
130
|
+
h_file.section do |struct|
|
|
131
|
+
enumerate_sections do |section_key, enumerate_keys|
|
|
132
|
+
struct.writeln 'struct %s {' % section_key
|
|
133
|
+
struct.section do |section_struct|
|
|
134
|
+
enumerate_keys.call do |key, value, comment|
|
|
135
|
+
if documented?
|
|
136
|
+
section_struct.writeln '/// %s' % (comment || value) #unless comment.nil?
|
|
137
|
+
end
|
|
138
|
+
section_struct.writeln '__unsafe_unretained NSString *%s;' % key
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
struct.writeln '} %s;' % section_key
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
h_file.writeln '} %s;' % resources_constant_name
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
def build_impl_contents m_file
|
|
148
|
+
m_file.writeln BANNER
|
|
149
|
+
m_file.writeln
|
|
150
|
+
m_file.writeln '#import "R.h"'
|
|
151
|
+
m_file.writeln
|
|
152
|
+
m_file.writeln 'const struct %s %s = {' % [resources_constant_name, resources_constant_name]
|
|
153
|
+
m_file.section do |struct|
|
|
154
|
+
enumerate_sections do |section_key, enumerate_keys|
|
|
155
|
+
struct.writeln '.%s = {' % section_key
|
|
156
|
+
struct.section do |section_struct|
|
|
157
|
+
enumerate_keys.call do |key, value|
|
|
158
|
+
section_struct.writeln '.%s = @"%s",' % [key, value]
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
struct.writeln '},'
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
m_file.writeln '};'
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
def enumerate_sections
|
|
168
|
+
# Iterate sections ordered by key
|
|
169
|
+
for section_key, section_content in @sections.sort
|
|
170
|
+
# Pass section key and block to yield the keys ordered
|
|
171
|
+
proc = Proc.new do |&block|
|
|
172
|
+
for key, value in section_content.sort
|
|
173
|
+
if value.is_a? Hash
|
|
174
|
+
block.call key, value[:value], value[:comment]
|
|
175
|
+
else
|
|
176
|
+
block.call key, value, nil
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
end
|
|
180
|
+
yield section_key, proc
|
|
181
|
+
end
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
class XCRes::StringBuilder
|
|
2
|
+
|
|
3
|
+
attr_accessor :indentation_string
|
|
4
|
+
attr_accessor :result
|
|
5
|
+
|
|
6
|
+
def initialize
|
|
7
|
+
self.indentation_string = ' '
|
|
8
|
+
self.result = ''
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def << input
|
|
12
|
+
# Only indent string inputs on nested / delegating string builders
|
|
13
|
+
input = self.indentation_string + input unless result.is_a? String
|
|
14
|
+
|
|
15
|
+
self.result << input
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
alias write :<<
|
|
19
|
+
|
|
20
|
+
def writeln input=''
|
|
21
|
+
self << input + "\n"
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def section &block
|
|
25
|
+
builder = self.class.new
|
|
26
|
+
builder.indentation_string = self.indentation_string
|
|
27
|
+
builder.result = self
|
|
28
|
+
block.call builder
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
end
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
require 'xcres/command/project_command'
|
|
2
|
+
require 'xcres/helper/file_helper'
|
|
3
|
+
require 'xcres/builder/resources_builder'
|
|
4
|
+
require 'xcres/analyzer/aggregate_analyzer'
|
|
5
|
+
require 'xcres/analyzer/resources_aggregate_analyzer'
|
|
6
|
+
require 'xcres/analyzer/strings_analyzer'
|
|
7
|
+
|
|
8
|
+
# The +BuildCommand+ builds the resources index files.
|
|
9
|
+
#
|
|
10
|
+
class XCRes::BuildCommand < XCRes::ProjectCommand
|
|
11
|
+
|
|
12
|
+
include XCRes::FileHelper
|
|
13
|
+
|
|
14
|
+
inherit_parameters!
|
|
15
|
+
parameter '[OUTPUT_PATH]', 'Path where to write to', attribute_name: :output_path
|
|
16
|
+
|
|
17
|
+
def execute
|
|
18
|
+
super
|
|
19
|
+
|
|
20
|
+
# Derive the name for the resources constant file
|
|
21
|
+
self.resources_constant_name ||= derive_resources_constant_name
|
|
22
|
+
|
|
23
|
+
# Locate output path
|
|
24
|
+
self.output_path = locate_output_path
|
|
25
|
+
|
|
26
|
+
build do |builder|
|
|
27
|
+
analyzer = XCRes::AggregateAnalyzer.new(target)
|
|
28
|
+
analyzer.exclude_file_patterns = exclude_file_patterns
|
|
29
|
+
analyzer.logger = logger
|
|
30
|
+
analyzer.add_with_class(XCRes::ResourcesAggregateAnalyzer, shorten_keys: true)
|
|
31
|
+
analyzer.add_with_class(XCRes::StringsAnalyzer, default_language: default_language)
|
|
32
|
+
sections = analyzer.analyze
|
|
33
|
+
|
|
34
|
+
sections.each do |section|
|
|
35
|
+
builder.add_section section.name, section.items, section.options
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
success 'Successfully updated: %s', "#{output_path}.h"
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def derive_resources_constant_name
|
|
43
|
+
# Fall back to `basename OUTPUT_PATH` or 'R' if both are not given
|
|
44
|
+
if output_path != nil && !File.directory?(output_path)
|
|
45
|
+
basename_without_ext(output_path)
|
|
46
|
+
else
|
|
47
|
+
'R'
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def output_dir
|
|
52
|
+
if output_path.nil?
|
|
53
|
+
# Use project dir, if no output path was set
|
|
54
|
+
Pathname(xcodeproj_file_path) + '..'
|
|
55
|
+
else
|
|
56
|
+
path = Pathname(output_path)
|
|
57
|
+
if path.directory?
|
|
58
|
+
path
|
|
59
|
+
else
|
|
60
|
+
path + '..'
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def locate_output_path
|
|
66
|
+
output_dir.realdirpath + resources_constant_name
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def build
|
|
70
|
+
# Prepare builder
|
|
71
|
+
builder = XCRes::ResourcesBuilder.new
|
|
72
|
+
builder.output_path = output_path
|
|
73
|
+
builder.logger = logger
|
|
74
|
+
builder.documented = documented?
|
|
75
|
+
builder.resources_constant_name = resources_constant_name
|
|
76
|
+
|
|
77
|
+
yield builder
|
|
78
|
+
|
|
79
|
+
# Write the files, if needed
|
|
80
|
+
builder.build
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
end
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
require 'clamp'
|
|
2
|
+
require 'xcres/logger'
|
|
3
|
+
|
|
4
|
+
# Base class for commands
|
|
5
|
+
#
|
|
6
|
+
class XCRes::Command < Clamp::Command
|
|
7
|
+
|
|
8
|
+
option ['--silent'], :flag, 'Show nothing'
|
|
9
|
+
option ['--[no-]ansi'], :flag, 'Show output without ANSI codes', default: true
|
|
10
|
+
option ['-v', '--verbose'], :flag, 'Show more debugging information'
|
|
11
|
+
|
|
12
|
+
# Run the command, with the specified arguments.
|
|
13
|
+
#
|
|
14
|
+
# This calls {#parse} to process the command-line arguments,
|
|
15
|
+
# then delegates to {#execute}.
|
|
16
|
+
#
|
|
17
|
+
# @param [Array<String>] arguments command-line arguments
|
|
18
|
+
#
|
|
19
|
+
def run(arguments)
|
|
20
|
+
super
|
|
21
|
+
rescue Clamp::HelpWanted => e
|
|
22
|
+
raise e # Clamp will handle this for us
|
|
23
|
+
rescue StandardError => error
|
|
24
|
+
fail error
|
|
25
|
+
exit 1
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def execute
|
|
29
|
+
# Configure logger
|
|
30
|
+
configure_logger
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
#----------------------------------------------------------------------------#
|
|
34
|
+
|
|
35
|
+
# @!group Logger
|
|
36
|
+
|
|
37
|
+
# Lazy-instantiate a logger
|
|
38
|
+
#
|
|
39
|
+
def logger
|
|
40
|
+
@logger ||= XCRes::Logger.new
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Delegate log level methods to the logger
|
|
44
|
+
#
|
|
45
|
+
delegate :inform, :log, :success, :warn, :fail, to: :logger
|
|
46
|
+
|
|
47
|
+
# Checks the configured option to configure the logger
|
|
48
|
+
#
|
|
49
|
+
def configure_logger
|
|
50
|
+
logger.silent = silent?
|
|
51
|
+
logger.colored = ansi?
|
|
52
|
+
if verbose?
|
|
53
|
+
logger.verbose = verbose?
|
|
54
|
+
log 'Verbose mode is enabled.'
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
end
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
require 'xcres/command/project_command'
|
|
2
|
+
require 'xcres/command/build_command'
|
|
3
|
+
|
|
4
|
+
# The +InstallCommand+ integrates a build phase to the Xcode project,
|
|
5
|
+
# so that on each build the resources index will be rebuild, if needed.
|
|
6
|
+
#
|
|
7
|
+
class XCRes::InstallCommand < XCRes::ProjectCommand
|
|
8
|
+
|
|
9
|
+
BUILD_PHASE_NAME = 'Build Resource-Index'
|
|
10
|
+
|
|
11
|
+
inherit_parameters!
|
|
12
|
+
|
|
13
|
+
# Execute the command
|
|
14
|
+
#
|
|
15
|
+
# @return [void]
|
|
16
|
+
#
|
|
17
|
+
def execute
|
|
18
|
+
super
|
|
19
|
+
|
|
20
|
+
# Locate the parent group, where the built files will been added to
|
|
21
|
+
parent_group = find_parent_group
|
|
22
|
+
|
|
23
|
+
# Locate the output path
|
|
24
|
+
output_path = parent_group.real_path + 'Resources/R'
|
|
25
|
+
|
|
26
|
+
inform 'Execute build first:'
|
|
27
|
+
build(output_path)
|
|
28
|
+
|
|
29
|
+
integrate!(output_path, parent_group)
|
|
30
|
+
|
|
31
|
+
success 'Successfully integrated into %s', project_path
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Find parent group, where the built files will been added to.
|
|
35
|
+
# It will return the first group, which was found of the following list.
|
|
36
|
+
# * 'Supporting Files' group
|
|
37
|
+
# * target-specific group
|
|
38
|
+
# * main group
|
|
39
|
+
#
|
|
40
|
+
# @raise [ArgumentError]
|
|
41
|
+
# if no main group exists, which means that the project is invalid
|
|
42
|
+
#
|
|
43
|
+
# @return [PBXGroup]
|
|
44
|
+
#
|
|
45
|
+
def find_parent_group
|
|
46
|
+
# Get main group and ensure that it exists
|
|
47
|
+
main_group = project.main_group
|
|
48
|
+
raise ArgumentError, "Didn't found main group" if main_group.nil?
|
|
49
|
+
|
|
50
|
+
# Get target-specific group, if the default project layout is in use
|
|
51
|
+
src_group = main_group.groups.find { |g| g.path == target.name }
|
|
52
|
+
if src_group != nil
|
|
53
|
+
log "Found target group, will use its path as base output path."
|
|
54
|
+
else
|
|
55
|
+
log "Didn't found target group, expected a group with path '#{target.name}'."
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Find 'Supporting Files' group
|
|
59
|
+
groups = main_group.recursive_children_groups
|
|
60
|
+
support_files_group = groups.find { |g| g.name == 'Supporting Files' }
|
|
61
|
+
warn "Didn't found support files group" if support_files_group.nil?
|
|
62
|
+
|
|
63
|
+
support_files_group || src_group || main_group
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# Trigger a build for the current project
|
|
67
|
+
#
|
|
68
|
+
# @param [Pathname] output_path
|
|
69
|
+
# the argument OUTPUT_PATH for the build subcommand
|
|
70
|
+
#
|
|
71
|
+
# @return [void]
|
|
72
|
+
#
|
|
73
|
+
def build(output_path)
|
|
74
|
+
build_cmd = XCRes::BuildCommand.new("#{invocation_path} build", context, attribute_values)
|
|
75
|
+
build_cmd.logger.indentation = ' '
|
|
76
|
+
build_cmd.run([project_path.to_s, output_path.relative_path_from(Pathname.pwd).to_s])
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# Integrate the build phase and add the built files to the project
|
|
80
|
+
#
|
|
81
|
+
# @param [Pathname] output_path
|
|
82
|
+
# the argument OUTPUT_PATH for the build subcommand
|
|
83
|
+
#
|
|
84
|
+
# @param [PBXGroup] parent_group
|
|
85
|
+
# the group where to integrate
|
|
86
|
+
#
|
|
87
|
+
# @return [void]
|
|
88
|
+
#
|
|
89
|
+
def integrate!(output_path, parent_group)
|
|
90
|
+
# Find or create shell script build phase
|
|
91
|
+
build_phase = target.shell_script_build_phases.find do |bp|
|
|
92
|
+
bp.name == BUILD_PHASE_NAME
|
|
93
|
+
end
|
|
94
|
+
build_phase ||= target.new_shell_script_build_phase(BUILD_PHASE_NAME)
|
|
95
|
+
|
|
96
|
+
# Remove build phase to re-insert before compile sources
|
|
97
|
+
target.build_phases.delete(build_phase)
|
|
98
|
+
index = target.build_phases.index(target.source_build_phase)
|
|
99
|
+
target.build_phases.insert(index, build_phase)
|
|
100
|
+
|
|
101
|
+
# Set shell script
|
|
102
|
+
script_output_path = output_path.relative_path_from(src_root_path)
|
|
103
|
+
build_phase.shell_script = "xcres --no-ansi build $PROJECT_FILE_PATH $SRCROOT/#{script_output_path}\n"
|
|
104
|
+
|
|
105
|
+
# Find or create 'Resources' group in 'Supporting Files'
|
|
106
|
+
res_group = parent_group.groups.find { |g| g.name == 'Resources' }
|
|
107
|
+
res_group ||= parent_group.new_group('Resources', Pathname('Resources'))
|
|
108
|
+
|
|
109
|
+
# Find or create references to resources index files
|
|
110
|
+
h_file = res_group.find_file_by_path('R.h') || res_group.new_file('R.h')
|
|
111
|
+
m_file = res_group.find_file_by_path('R.m') || res_group.new_file('R.m')
|
|
112
|
+
|
|
113
|
+
# Add .m file to source build phase, if it doesn't not already exist there
|
|
114
|
+
target.source_build_phase.add_file_reference(m_file, true)
|
|
115
|
+
|
|
116
|
+
# Add .h file to prefix header
|
|
117
|
+
prefix_headers.each do |path|
|
|
118
|
+
realpath = src_root_path + path
|
|
119
|
+
next unless File.exist?(realpath)
|
|
120
|
+
File.open(realpath, 'a+') do |f|
|
|
121
|
+
import_snippet = "#import \"#{h_file.path}\"\n"
|
|
122
|
+
unless f.readlines.include?(import_snippet)
|
|
123
|
+
f.write "\n#{import_snippet}"
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
project.save()
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
# Return a relative path to the project
|
|
132
|
+
#
|
|
133
|
+
# @return [Pathname]
|
|
134
|
+
#
|
|
135
|
+
def project_path
|
|
136
|
+
project.path.relative_path_from(Pathname.pwd)
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
# Return the path, which would be represented by the value of the
|
|
140
|
+
# build setting `$SRCROOT`.
|
|
141
|
+
#
|
|
142
|
+
# @return [Pathname]
|
|
143
|
+
#
|
|
144
|
+
def src_root_path
|
|
145
|
+
project_path.realpath + '..'
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
# Return a hash of attribute values
|
|
149
|
+
#
|
|
150
|
+
# @return [Hash{Clamp::Attribute::Definition => #to_s}]
|
|
151
|
+
#
|
|
152
|
+
def attribute_values
|
|
153
|
+
attribute_values = {}
|
|
154
|
+
self.class.recognised_options.each do |attribute|
|
|
155
|
+
if attribute.of(self).defined?
|
|
156
|
+
attribute_values[attribute] = attribute.of(self).get
|
|
157
|
+
end
|
|
158
|
+
end
|
|
159
|
+
attribute_values
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
# Discover prefix header by build settings of the application target
|
|
163
|
+
#
|
|
164
|
+
# @return [Set<Pathname>]
|
|
165
|
+
# the relative paths to the .pch files
|
|
166
|
+
#
|
|
167
|
+
def prefix_headers
|
|
168
|
+
@prefix_headers ||= target.build_configurations.map do |config|
|
|
169
|
+
Pathname(config.build_settings['GCC_PREFIX_HEADER'])
|
|
170
|
+
end.flatten.to_set
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
require 'xcodeproj'
|
|
2
|
+
require 'xcres/logger'
|
|
3
|
+
require 'xcres/command/command'
|
|
4
|
+
require 'xcres/command/build_command'
|
|
5
|
+
require 'xcres/command/install_command'
|
|
6
|
+
require 'xcres/command/version_command'
|
|
7
|
+
|
|
8
|
+
class XCRes::MainCommand < XCRes::Command
|
|
9
|
+
|
|
10
|
+
subcommand 'build', 'Build the resources index files', XCRes::BuildCommand
|
|
11
|
+
subcommand 'install', 'Install a build phase into the project', XCRes::InstallCommand
|
|
12
|
+
subcommand 'version', 'Show the gem version', XCRes::VersionCommand
|
|
13
|
+
|
|
14
|
+
end
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
require 'xcres/command/command'
|
|
2
|
+
require 'xcodeproj'
|
|
3
|
+
|
|
4
|
+
# The +ProjectCommand+ is the base class for commands,
|
|
5
|
+
# which analyze or modify Xcode projects.
|
|
6
|
+
#
|
|
7
|
+
class XCRes::ProjectCommand < XCRes::Command
|
|
8
|
+
|
|
9
|
+
option ['--[no-]documented'], :flag, 'Add documentation to the generated files', default: true
|
|
10
|
+
#option ['-d', '--dry-run'], :flag, 'Does nothing on the file system'
|
|
11
|
+
|
|
12
|
+
option ['-t', '--target'], 'TARGET', 'Application target to use', attribute_name: :target_name
|
|
13
|
+
option ['-x', '--exclude'], 'FILE_PATTERN', 'File pattern which should be excluded (default: ["InfoPlist.strings"])', multivalued: true, attribute_name: :exclude_file_patterns, default: ['InfoPlist.strings']
|
|
14
|
+
option ['-n', '--name'], 'NAME', 'Name of the resources constant (default: `basename OUTPUT_PATH`)', attribute_name: :resources_constant_name
|
|
15
|
+
option ['-l', '--language'], 'LANGUAGE', 'Default language to build the keys', attribute_name: :default_language do |language|
|
|
16
|
+
raise ArgumentError.new 'Expected a two-letter code conforming ISO 639-1 as LANGUAGE' unless String(language).length == 2
|
|
17
|
+
language
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Define parameter in an inheritable way
|
|
21
|
+
#
|
|
22
|
+
def self.inherit_parameters!
|
|
23
|
+
parameter '[XCODEPROJ]', 'Xcode project file to inspect (automatically located on base of the current directory if not given)', attribute_name: :xcodeproj_file_path
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def execute
|
|
28
|
+
super
|
|
29
|
+
|
|
30
|
+
# Try to discover Xcode project at given path.
|
|
31
|
+
self.xcodeproj_file_path = find_xcodeproj
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
#----------------------------------------------------------------------------#
|
|
36
|
+
|
|
37
|
+
# @!group Xcode Project
|
|
38
|
+
|
|
39
|
+
# Opens the Xcode project, if not already opened
|
|
40
|
+
#
|
|
41
|
+
# @return [Xcodeproj::Project]
|
|
42
|
+
# the Xcode project
|
|
43
|
+
#
|
|
44
|
+
def project
|
|
45
|
+
@project ||= Xcodeproj::Project.open(xcodeproj_file_path)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Find the application target to use
|
|
49
|
+
#
|
|
50
|
+
# @return [PBXNativeTarget]
|
|
51
|
+
#
|
|
52
|
+
def target
|
|
53
|
+
if target_name != nil
|
|
54
|
+
application_targets.find { |t| t.name == target }
|
|
55
|
+
else
|
|
56
|
+
if application_targets.count == 1
|
|
57
|
+
application_targets.first
|
|
58
|
+
else
|
|
59
|
+
raise ArgumentError.new 'Multiple application target in project. ' \
|
|
60
|
+
'Please select one by specifying the option `--target TARGET`.'
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# Find all application targets in the project
|
|
66
|
+
#
|
|
67
|
+
# @return [Array<PBXNativeTarget>]
|
|
68
|
+
#
|
|
69
|
+
def application_targets
|
|
70
|
+
@application_targets ||= project.targets.select do |target|
|
|
71
|
+
target.is_a?(Xcodeproj::Project::Object::PBXNativeTarget) \
|
|
72
|
+
&& target.product_type == Xcodeproj::Constants::PRODUCT_TYPE_UTI[:application]
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def find_xcodeproj
|
|
77
|
+
path = discover_xcodeproj_file_path!
|
|
78
|
+
|
|
79
|
+
if !Dir.exist?(path) || !File.exist?(path + '/project.pbxproj')
|
|
80
|
+
raise ArgumentError.new 'XCODEPROJ at %s was not found or is not a ' \
|
|
81
|
+
'valid Xcode project.' % path
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
success 'Use %s as XCODEPROJ.', path
|
|
85
|
+
|
|
86
|
+
return path
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def discover_xcodeproj_file_path!
|
|
90
|
+
if xcodeproj_file_path.nil?
|
|
91
|
+
warn 'Argument XCODEPROJ is not set. Use the current directory.'
|
|
92
|
+
discover_xcodeproj_file_path_in_dir! '.'
|
|
93
|
+
elsif Dir.exist?(xcodeproj_file_path) && !File.fnmatch('*.xcodeproj', xcodeproj_file_path)
|
|
94
|
+
warn 'Argument XCODEPROJ is a directory. ' \
|
|
95
|
+
'Try to locate the Xcode project in this directory.'
|
|
96
|
+
discover_xcodeproj_file_path_in_dir! xcodeproj_file_path
|
|
97
|
+
else
|
|
98
|
+
xcodeproj_file_path
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def discover_xcodeproj_file_path_in_dir! dir
|
|
103
|
+
xcodeproj_file_paths = Dir[dir + '/*.xcodeproj']
|
|
104
|
+
if xcodeproj_file_paths.count == 0
|
|
105
|
+
raise ArgumentError.new 'Argument XCODEPROJ was not given and no ' \
|
|
106
|
+
'*.xcodeproj was found in current directory.'
|
|
107
|
+
end
|
|
108
|
+
xcodeproj_file_paths.first
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
module XCRes
|
|
2
|
+
module FileHelper
|
|
3
|
+
|
|
4
|
+
# Return the basename without its extname
|
|
5
|
+
# e.g: 'dir/test.jpg' => 'test'
|
|
6
|
+
#
|
|
7
|
+
# @param [String] file_path
|
|
8
|
+
#
|
|
9
|
+
# @return [String]
|
|
10
|
+
#
|
|
11
|
+
def basename_without_ext file_path
|
|
12
|
+
File.basename file_path, File.extname(file_path)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
end
|
|
16
|
+
end
|