Class: App

Inherits:
Object
  • Object
show all
Defined in:
lib/csa/app.rb

Instance Method Summary collapse

Constructor Details

#initialize(options) ⇒ App

Returns a new instance of App.



11
12
13
14
15
# File 'lib/csa/app.rb', line 11

def initialize(options)
  @name = options[:project_name].capitalize_first
  @template_url = options[:template_url]
  @use_default = options[:use_default]
end

Instance Method Details

#add_fastlaneObject



262
263
264
265
266
267
268
269
270
271
# File 'lib/csa/app.rb', line 262

def add_fastlane
  return unless system "which fastlane > /dev/null"
  return if @use_default
  question = CLI::UI.fmt("{{green:Do you want to add fastlane to your project?}} (y/n)")
  answer = CLI::UI.ask(question, default: "n")
  return unless answer == "y"
  Dir.chdir("#{@name}") do |_|
    system "fastlane init"
  end
end

#add_gitObject



212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
# File 'lib/csa/app.rb', line 212

def add_git
  return if Dir.exist?(Pathname("./#{@name}/.git"))

  if @use_default
    Dir.chdir("#{@name}") do |_|
      system "git init > /dev/null"
      puts "Initialized empty Git repository in ./#{@name}/.git/"
    end
    return
  end

  question = CLI::UI.fmt("{{green:Do you want to use git?}} (y/n)")
  answer = CLI::UI.ask(question, default: "y")
  if answer.downcase == "y"
    Dir.chdir("#{@name}") do |_|
      system "git init > /dev/null"
      puts "Initialized empty Git repository in ./#{@name}/.git/"
      question = CLI::UI.fmt("{{green:Repository url for the project: (enter to skip)?}}")
      @repo_url = CLI::UI.ask(question)
      @repo_url.strip!
      unless @repo_url.empty?
        system "git remote add origin #{@repo_url}"
        system "git push --set-upstream origin master"
      end
    end
  end
end

#clone_templateObject



35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/csa/app.rb', line 35

def clone_template
  if Dir.exist?(Pathname("./#{@name}"))
    question = CLI::UI.fmt("{{green:Folder #{@name} already exists, overwrite? (y/n)}}")
    override = CLI::UI.ask(question, default: "n")
    if override.downcase == "y"
      delete_file(@name)
    else
      exit(0)
    end
  end

  unless @template_url.empty?
    puts CLI::UI.fmt("{{green:git clone #{@template_url} #{@name}}}")
    system "git clone #{@template_url} #{@name}"
  else
    exit(0)
  end
  remove_userdata
end

#delete_file(name) ⇒ Object



65
66
67
68
# File 'lib/csa/app.rb', line 65

def delete_file(name)
  puts CLI::UI.fmt("{{green:deleting #{name}}}")
  system "find . -name #{name} -depth -exec rm -rf {} \\;"
end

#get_project_infoObject



124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
# File 'lib/csa/app.rb', line 124

def get_project_info
  if @use_default
    @author = "DEFAULT_AUTHOR"
    @organization = "DEFAULT_ORG"
    return
  end

  # get author and org name
  question_author = CLI::UI.fmt("{{green:Author for the project:}}")
  question_organization = CLI::UI.fmt("{{green:Organization Name for the project:}}")
  @author = CLI::UI.ask(question_author)
  @organization = CLI::UI.ask(question_organization)
  @author.strip!
  @author.gsub!(/[^a-zA-Z0-9]/, "")
  @organization.strip!
  @author = "DEFAULT_AUTHOR" if @author.empty?
  @organization = "DEFAULT_ORG" if @organization.empty?
  puts @author
  puts @organization
end

#get_template_author_organizationObject



77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/csa/app.rb', line 77

def get_template_author_organization
  app_delegate_path = Dir.glob("./#{@name}/**/**/*AppDelegate*.swift").last
  raise "Can't find your AppDelegate file" if app_delegate_path.nil?

  @template_author = File.open(app_delegate_path) do |file|
    file.each_line do |line|
      break line if /^\/\/ {2}Created by/ =~ line
    end
  end

  begin
    index1 = @template_author.index("by") + 2
    index2 = @template_author.index("on")
    @template_author = @template_author[0, index2]
    @template_author = @template_author[index1, index2]
    @template_author.strip!
  rescue
    @template_author = "DEFAULT_AUTHOR"
  end

  @template_organization = File.open(app_delegate_path) do |file|
    file.each_line do |line|
      break line if /^\/\/ {2}Copyright ©/ =~ line
    end
  end

  begin
    index1 = @template_organization.index("©") + 1
    index2 = @template_organization.index(".")
    @template_organization = @template_organization[0, index2]
    @template_organization = @template_organization[index1, index2]
    @template_organization.strip!
  rescue
    @template_organization = "DEFAULT_ORG"
  end
end

#get_template_infoObject



70
71
72
73
74
75
# File 'lib/csa/app.rb', line 70

def get_template_info
  template_path = Dir.glob("./#{@name}/**/**/*.xcodeproj").first
  @template_name = File.basename(template_path, ".xcodeproj")
  @template_name_other = @template_name.gsub(/[^a-zA-Z0-9]/, "_")
  get_template_author_organization
end

#install_podsObject



240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
# File 'lib/csa/app.rb', line 240

def install_pods
  return unless system "which pod > /dev/null"
  Dir.chdir("#{@name}") do |_|
    if File.exists?("Podfile")
      if @use_default
        system "pod deintegrate"
        system "pod install"
        return
      end

      question = CLI::UI.fmt("{{green:Podfile detected, do you want to install pods now?}}")
      answer = CLI::UI.ask(question, options: %w(install skip))
      case answer
      when "install"
        system "pod deintegrate"
        system "pod install"
      else break
      end
    end
  end
end

#open_projectObject



273
274
275
276
277
278
279
280
281
282
283
284
# File 'lib/csa/app.rb', line 273

def open_project
  begin
    Dir.chdir("#{@name}") do |_|
      system "open ."
    end
    project = Dir.glob("./**/**/#{@name}.xcworkspace").first
    project = Dir.glob("./**/**/#{@name}.xcodeproj").first if project.nil?
    system "open #{project}"
  rescue Exception
    # ignore
  end
end

#remove_userdataObject



55
56
57
58
59
60
61
62
63
# File 'lib/csa/app.rb', line 55

def remove_userdata
  Dir.chdir("#{@name}") do |_|
    delete_file("Pods")
    delete_file(".git")
    delete_file(".DS_Store")
    delete_file("xcuserdata")
    delete_file("xcshareddata")
  end
end

#rename(original_name) ⇒ Object



157
158
159
160
161
162
# File 'lib/csa/app.rb', line 157

def rename(original_name)
  name_new = original_name.sub(Regexp.new(Regexp.escape(@template_name), Regexp::IGNORECASE), @name)
  name_new = name_new.sub(Regexp.new(Regexp.escape(@template_name_other), Regexp::IGNORECASE), @name)
  File.rename(original_name, name_new) if original_name != name_new
  name_new
end

#rename_files(path = Pathname("./#{@name}")) ⇒ Object



145
146
147
148
149
150
151
152
153
154
155
# File 'lib/csa/app.rb', line 145

def rename_files(path = Pathname("./#{@name}"))
  puts "updating #{path}"
  path = rename(path)
  if File.directory?(path)
    Dir.each_child(path) do |file|
      rename_files(path + file)
    end
  else
    update_content(path)
  end
end

#runObject



17
18
19
20
21
# File 'lib/csa/app.rb', line 17

def run
  validate_project_name
  setup_template
  setup_project
end

#set_bundle_identifiersObject



187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
# File 'lib/csa/app.rb', line 187

def set_bundle_identifiers
  project_path = Dir.glob("./#{@name}/**/**/#{@name}.xcodeproj").first
  project = Xcodeproj::Project.open(project_path)
  project.root_object.attributes["ORGANIZATIONNAME"] = @organization
  project.targets.each do |target|
    target.build_configurations.each do |config|
      config.build_settings["PRODUCT_BUNDLE_IDENTIFIER"] = "com.#{@organization.downcase.gsub(/[^a-zA-Z0-9]/, "-")}.#{@name.downcase}.#{target}.#{config}"
    end
  end
  project.save
  return if @use_default

  # change bundle identifier
  puts CLI::UI.fmt("{{cyan:Let's setup your bundle identifiers}}")
  project.targets.each do |target|
    target.build_configurations.each do |config|
      original_bundle_identifier = config.build_settings["PRODUCT_BUNDLE_IDENTIFIER"]
      question = CLI::UI.fmt("Bundle Identifier of Target {{green:#{target}}} for {{green:#{config}}}")
      answer = CLI::UI.ask(question, default: original_bundle_identifier)
      config.build_settings["PRODUCT_BUNDLE_IDENTIFIER"] = answer if answer != original_bundle_identifier
    end
  end
  project.save
end

#setup_projectObject



114
115
116
117
118
119
120
121
122
# File 'lib/csa/app.rb', line 114

def setup_project
  get_project_info
  rename_files
  set_bundle_identifiers
  add_git
  install_pods
  add_fastlane
  open_project
end

#setup_templateObject



30
31
32
33
# File 'lib/csa/app.rb', line 30

def setup_template
  clone_template
  get_template_info
end

#update_content(path) ⇒ Object



164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
# File 'lib/csa/app.rb', line 164

def update_content(path)
  begin
    file = File.new("#{path}_new", "w+")
    origin = File.open(path, "r:UTF-8")
    today = Date.today.strftime("%d/%m/%y")
    origin.each do |line|
      line = "//  Created by #{@author} on #{today}." if /^\/\/ {2}Created by/ =~ line
      line = "//  Copyright © #{Time.new.strftime("%Y")} #{@organization}. All rights reserved." if /^\/\/ {2}Copyright ©/ =~ line
      line.gsub!(Regexp.new(Regexp.escape(@template_name), Regexp::IGNORECASE), @name)
      line.gsub!(Regexp.new(Regexp.escape(@template_name_other), Regexp::IGNORECASE), @name)
      line.gsub!(Regexp.new(Regexp.escape(@template_organization), Regexp::IGNORECASE), @organization)
      line.gsub!(Regexp.new(Regexp.escape(@template_author), Regexp::IGNORECASE), @author)
      file.puts line
    end
    origin.close
    file.close
    File.delete(origin)
    File.rename("#{path}_new", path)
  rescue Exception
    # ignored
  end
end

#validate_project_nameObject



23
24
25
26
27
28
# File 'lib/csa/app.rb', line 23

def validate_project_name
  raise "Name is required" unless @name
  raise "Project name cannot contain spaces" if @name =~ /\s/
  raise "Project name cannot begin with a '.'" if @name[0, 1] == "."
  raise "Project name should only contain numbers and letters" if @name =~ /[^a-zA-Z0-9]/
end