Automated Full Project Backup in Xcode
I have been going through a lot of tutorials lately. One thing I have noticed is when things go wrong after a chapter or two it is difficult to get back to where you were when things were working.
I have been giving Subversion a go but it is not as easy as you would think to roll back to a previous version. Plus I have to remember to do it. Two or three builds later and the lightbulb goes off, "When was the last time I committed to the repository?" Not good.
This script is very simple and should be used only for training or short build phases. The reason is that the entire project folder, minus the build folder, is backed-up during each build. Exactly what we need when wanting to roll back to the last chapter we were on in the book but not so good for large projects with hundreds of builds. I have a better, although not perfect by any means solution here.
How It WorksDuring each build you will be asked if you want to do a backup. If you click 'Yes' then another dialog will give you the opportunity to provide notes for this build. If you are doing tutorials this is a good place to put something like 'Just finished ch 4 page 95.' This will be added to a '_NOTES.txt' file inside this backup folder as well as added to an '_All_NOTES.txt' file inside the backup projects folder. This is for easy viewing of what you were doing during each build.
If you would like to disable the 'ask before backup' feature simply set ASK_BEFORE_BACKUP to false.
InstallationInstallation instructions here.
Requirements
#!/usr/bin/env ruby -w
# Code from O'Reilly's 'Ruby Cookbook' page 220
# Versions file or folder names
# Eg. MyProj, MyProj.001, MyProj.002
class File
def File.versioned_name(base, first_suffix='.0001')
suffix = nil
folder_name = base
while File.exists?(folder_name)
suffix = (suffix ? suffix.succ : first_suffix)
folder_name = base + suffix
end
return folder_name
end
end
class BackupXcodeProject
require 'fileutils'
require 'time'
require 'appscript'; include Appscript
require 'osax'; include OSAX
MESSAGE_HEADER = 'BACKING UP PROJECT MESSAGE'
ASK_BEFORE_BACKUP = true
def initialize
instantiate_variables
end
def main_worker_bee
backup_question if ASK_BEFORE_BACKUP
create_parent_folder
create_archive_folder
create_versioned_folder
add_notes
copy_files
delete_build_folder
end
def instantiate_variables
@proj_dir = ENV['PROJECT_DIR']
@proj_name = ENV['PROJECT_NAME']
@backup_dir = "#{ENV['HOME']}/desktop/BackupXcode"
@time_format = '24'
end
def create_parent_folder
begin
FileUtils.mkdir(@backup_dir) if !File.exists?(@backup_dir)
rescue
log_message("ERROR in create_parent_folder\nerror => #{$!}")
end
end
def create_archive_folder
begin
@archive_folder_name = "#{@backup_dir}/#{@proj_name}"
FileUtils.mkdir(@archive_folder_name) if !File.exists?(@archive_folder_name)
rescue
log_message("ERROR in create_archive_folder\nerror => #{$!}")
end
end
def create_versioned_folder
begin
time_stamp = (@time_format == '24' ? `date +'%Y.%m.%d_%H.%M.%S'` : `date +'%Y.%m.%d_%I.%M.%S'`)
folder_name = "#{time_stamp.chomp}_#{@proj_name}"
@archive_versioned_name = File.versioned_name("#{@archive_folder_name}/#{folder_name}")
FileUtils.mkdir(@archive_versioned_name)
rescue
log_message("ERROR in create_versioned_folder\nerror => #{$!}")
end
end
def backup_question
button = osax.display_dialog('Do you want to backup now?',
:buttons => ['No', 'Yes'],
:default_button => 2)
exit if button[:button_returned] == 'No'
end
def add_notes
text = osax.display_dialog("Notes for this backup.", :default_answer => "\n\n\n\n\n")
notes = text[:text_returned]
all_notes = "\n------------------------------------\n#{File.basename(@archive_versioned_name)}\n\t#{notes}\n"
open("#{@archive_folder_name}/_ALL_NOTES.txt", 'a') { |f| f.puts all_notes }
open("#{@archive_versioned_name}/_NOTES.txt", 'w') { |f| f.puts notes }
end
def copy_files
return system("/usr/bin/ditto #{@proj_dir} #{@archive_versioned_name}")
end
def delete_build_folder
system("rm -r #{@archive_versioned_name}/build/")
end
def log_message(msg)
puts "\n\n----------------------------------------------"
puts MESSAGE_HEADER
puts msg
puts "----------------------------------------------\n\n"
end
end
if __FILE__ == $0
backup_files = BackupXcodeProjectFiles.new
backup_files.main_worker_bee
backup_files.log_message('Looks like all went well!')
end
