Last active
January 18, 2022 09:37
-
-
Save tmspzz/ddf64f679f4a862c4e3279e7294d8a58 to your computer and use it in GitHub Desktop.
An opinionated workflow for Carthage
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env ruby | |
# Copyright (c) 2016 Tommaso Piazza | |
# 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 | |
require 'fileutils' | |
require 'xcodeproj' | |
require 'colored' | |
require 'terminal-notifier' | |
require 'inifile' | |
#CONSTANTS | |
PROJECT_DIRECTORY = Dir.pwd | |
CARTHAGE_CHECKOUT_DIR = "Carthage/Checkouts" | |
CARTHAGE_BUILD_DIR = "Carthage/Build" | |
CARTHAGE_BUILD_DIR_BKP = "Carthage/_Build" | |
CARTHAGE_BUILD_DIR_IOS = "#{CARTHAGE_BUILD_DIR}/iOS" | |
$TARGET_NAME = "" | |
COPY_FRAMEWORK_PHASE_NAME = "Carthage Copy Frameworks" | |
ROMEFILE = "Romefile" | |
REPOSITORY_MAP = "RepositoryMap" | |
$PROJECT_MAP = {} | |
#FUNCTIONS | |
def get_framework_checkout_dir(framework_name) | |
framework_checkout_dir = File.join PROJECT_DIRECTORY, CARTHAGE_CHECKOUT_DIR, framework_name | |
framework_checkout_dir_bkp = File.join PROJECT_DIRECTORY, CARTHAGE_CHECKOUT_DIR, "_" << framework_name | |
return framework_checkout_dir, framework_checkout_dir_bkp | |
end | |
def get_carthage_build_dir(dir) | |
framework_build_dir = File.join dir, CARTHAGE_BUILD_DIR | |
framework_build_dir_bkp = File.join dir, CARTHAGE_BUILD_DIR_BKP | |
return framework_build_dir, framework_build_dir_bkp | |
end | |
def link_target_framework(framework_name) | |
framework_src_dir = File.join PROJECT_DIRECTORY, "..", framework_name | |
if Dir.exist? framework_src_dir | |
framework_checkout_dir, framework_checkout_dir_bkp = get_framework_checkout_dir framework_name | |
if File.symlink? framework_checkout_dir | |
puts "Nothing to do #{framework_checkout_dir} seems already set up for development." | |
else | |
#backup the current framework checkout | |
FileUtils.mv framework_checkout_dir, framework_checkout_dir_bkp if Dir.exist? framework_checkout_dir | |
#link the directory of the framwork to co-develop to Carthage/Checkouts | |
FileUtils.ln_s framework_src_dir, framework_checkout_dir | |
#backup the framwork's build folder | |
framework_build_dir, framework_build_dir_bkp = get_carthage_build_dir framework_checkout_dir | |
FileUtils.mv framework_build_dir, framework_build_dir_bkp if Dir.exist?(framework_build_dir) | |
#link the build folders | |
FileUtils.ln_s (File.join PROJECT_DIRECTORY, CARTHAGE_BUILD_DIR), framework_build_dir | |
end | |
else | |
puts "Error: Missing required dir #{framework_src_dir}." | |
return | |
end | |
end | |
def unlink_target_framework(framework_name) | |
framework_checkout_dir, framework_checkout_dir_bkp = get_framework_checkout_dir framework_name | |
framework_build_dir, framework_build_dir_bkp = get_carthage_build_dir framework_checkout_dir | |
if File.symlink? framework_checkout_dir | |
FileUtils.rm framework_build_dir if File.symlink? framework_build_dir | |
FileUtils.mv framework_build_dir_bkp, framework_build_dir if (Dir.exist? framework_build_dir_bkp) and !(Dir.exist? framework_build_dir) | |
FileUtils.rm framework_checkout_dir if File.symlink? framework_checkout_dir | |
FileUtils.mv framework_checkout_dir_bkp, framework_checkout_dir if (Dir.exist? framework_checkout_dir_bkp) and !(Dir.exist? framework_checkout_dir) | |
end | |
end | |
def open_target_xcode_project() | |
project_path = File.join PROJECT_DIRECTORY, "#{$TARGET_NAME}.xcodeproj" | |
project = Xcodeproj::Project.open(project_path) | |
return project | |
end | |
def save_target_xcode_project(project) | |
project.save("#{$TARGET_NAME} Dev.xcodeproj") | |
end | |
def add_framework_to_project(project, framework_name) | |
real_green_target = project.targets.select do |target| | |
target.name == $TARGET_NAME | |
end .first | |
framework_project_name = $PROJECT_MAP[framework_name] | |
if framework_project_name == nil | |
return | |
end | |
framework_project_path = File.join "..", framework_name, (framework_project_name + ".xcodeproj") | |
framework_project = Xcodeproj::Project.open(framework_project_path) | |
framework_target = framework_project.targets.select do |target| | |
target.name == framework_project_name | |
end .first | |
project.main_group.new_reference framework_project_path | |
real_green_target.add_dependency framework_target | |
framework_build_phase = real_green_target.frameworks_build_phases | |
frameworks_group = project.main_group["#{$TARGET_NAME}/Frameworks/"] | |
old_f = frameworks_group["#{framework_project_name}.framework"] | |
frameworks_group.children.delete old_f | |
framework_product_reference = frameworks_group.new_product_ref_for_target(framework_target.name, :framework) | |
delete_ref = framework_build_phase.files_references.select do |ref| | |
ref.path.include? "#{CARTHAGE_BUILD_DIR_IOS}/#{framework_project_name}.framework" | |
end .first | |
framework_build_phase.remove_file_reference delete_ref | |
framework_build_phase.add_file_reference framework_product_reference | |
framework_shell_script_build_phases = real_green_target.shell_script_build_phases | |
carthage_copy_phase = framework_shell_script_build_phases.select do |phase| | |
phase.name == COPY_FRAMEWORK_PHASE_NAME | |
end .first | |
carthage_copy_phase.input_paths.delete_if do |s| | |
s.include? (framework_project_name + ".framework") | |
end | |
carthage_copy_phase.input_paths << "$(BUILT_PRODUCTS_DIR)/#{framework_project_name}.framework" | |
end | |
def start_notifying(interval) | |
pid = fork do | |
sleeping = 0 | |
while sleep interval do | |
sleeping += interval | |
TerminalNotifier.notify "Developing for #{sleeping/sleep_interval} hours", { :title => "🤖 develop.rb" , :subtitle => "#{ARGV[1]}" } | |
end | |
end | |
return pid | |
end | |
def read_project_map | |
romefile = nil | |
if File.exists? ROMEFILE | |
romefile = IniFile.load ROMEFILE | |
else | |
puts "Error: Missing Romefile" | |
exit 1 | |
end | |
$PROJECT_MAP = romefile["RepositoryMap"] | |
if $PROJECT_MAP == nil | |
puts "Error: Missing section #{REPOSITORY_MAP} in #{ROMEFILE}" | |
exit 1 | |
end | |
end | |
def update_target_name | |
$TARGET_NAME = ENV["TARGET_NAME"] | |
if $TARGET_NAME == nil | |
puts "Error: Enviroment variable "<< "TARGET_NAME" << " not found. Set this to the name of your project without .xcodeproj extension" | |
exit 1 | |
end | |
end | |
def print_help() | |
puts "develop.rb <subcommand> FRAMEWORK [ADDITIONAL_FRAMEWORKS]" | |
puts "" | |
puts "Subcommands:" | |
puts "\t start\t Starts development on FRAMEWORK. ADDITIONAL_FRAMEWORKS is a list of space separated frameworks." | |
puts "\t stop\t Stop development on FRAMEWORK. ADDITIONAL_FRAMEWORKS is a list of space separated frameworks. You should never need to call this directly" | |
puts "" | |
end | |
#MAIN | |
if ARGV.length > 1 | |
repos = ARGV.drop(1) | |
parent_pid = Process.pid | |
case ARGV[0] | |
when "start" | |
read_project_map | |
update_target_name | |
Signal.trap("INT") do | |
if Process.pid == parent_pid | |
puts | |
puts "Stopping development and cleaning up...".green | |
repos.each do | repo_name| | |
unlink_target_framework repo_name | |
end | |
exit | |
end | |
exit | |
end | |
project = open_target_xcode_project | |
puts project | |
repos.each do | repo_name| | |
link_target_framework repo_name | |
add_framework_to_project project, repo_name | |
end | |
save_target_xcode_project project | |
pid = start_notifying 3600 | |
puts "Press ^C to stop development".red | |
Process.wait2 pid | |
when "stop" | |
read_project_map | |
update_target_name | |
repos.each do | repo_name| | |
unlink_target_framework repo_name | |
end | |
else | |
print_help | |
end | |
else | |
print_help | |
end |
I am getting following error -
tariq$ ./develop.rb --help /Users/tariq/.rvm/rubies/ruby-2.4.0/lib/ruby/site_ruby/2.4.0/rubygems/core_ext/kernel_require.rb:120:in `require': cannot load such file -- terminal-notifier (LoadError) from /Users/tariq/.rvm/rubies/ruby-2.4.0/lib/ruby/site_ruby/2.4.0/rubygems/core_ext/kernel_require.rb:120:in `require' from ./develop.rb:21:in `<main>'
You can use gem install terminal-notifier
to fix this.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I am getting following error -