Class: PodBuilder::Command::UpdateLldbInit

Inherits:
Object
  • Object
show all
Defined in:
lib/pod_builder/command/update_lldbinit.rb

Class Method Summary collapse

Class Method Details

.call(options) ⇒ Object



7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/pod_builder/command/update_lldbinit.rb', line 7

def self.call(options)
  Configuration.check_inited
  
  argument_pods = ARGV.dup
  
  unless argument_pods.count > 0 
    return -1
  end
  unless argument_pods.count == 2
    raise "\n\nExpecting LLDBINIT_PATH and a single PATH to the folder containing the prebuilt framework's source code\n\n".red 
  end
      
  base_path = PodBuilder::basepath("")

  podfile_restore_content = File.read(PodBuilder::basepath("Podfile.restore"))
  app_podfile_content = File.read(PodBuilder::project_path("Podfile"))

  lldbinit_path = File.expand_path(argument_pods[0])
  lldbinit_content = File.exists?(lldbinit_path) ? File.read(lldbinit_path) : ""
  status_hash = podfiles_status_hash(app_podfile_content, podfile_restore_content)
  if lldbinit_content.include?("# <pb_md5:#{base_path}:#{status_hash}")
    puts "\n\nšŸŽ‰ already in sync!\n".green
    return 0
  end

  source_path = argument_pods[1]
  
  is_absolute = ["~", "/"].include?(source_path[0])
  if !is_absolute
    source_path = Pathname.new(File.join(base_path, source_path))
  end
  
  source_path = File.expand_path(source_path)
  
  framework_paths = Dir.glob("#{base_path}/**/*.framework")
  
  unless framework_paths.count > 0
    raise "\n\nNo prebuilt frameworks found in `#{framework_paths}`\n\n".red 
  end

  puts "Extracting debug information".yellow

  podspec_paths = Dir.glob("#{source_path}/**/*.podspec") + Dir.glob("#{source_path}/**/*.podspec.json")
  podspec_contents = podspec_paths.map { |t| File.read(t).gsub(/\s+/, "").gsub("\"", "'") }
  
  replace_paths = []
  
  framework_paths.each do |framework_path|
    name = File.basename(framework_path, File.extname(framework_path)) 
    executable_path = File.join(framework_path, name)

    podbuilder_plist = File.join(framework_path, Configuration.framework_plist_filename)

    plist = CFPropertyList::List.new(:file => podbuilder_plist)
    data = CFPropertyList.native_types(plist.value)

    original_compile_path = data["original_compile_path"]
    is_prebuilt = data.fetch("is_prebuilt", true)

    if original_compile_path.nil?
      puts "\n\n#{framework_path} was compiled with an older version of PodBuilder, please rebuild it to update `#{lldbinit_path}`"
      next
    end
    
    if is_prebuilt
      next
    end

    if podspec_path = find_podspec_path_for(name, podspec_paths, podspec_contents)
      if !is_development_pod(podspec_path, app_podfile_content)
        replace_paths.push("#{original_compile_path}/Pods/#{name},#{File.dirname(podspec_path)}")
      else
        puts "#{name} is in development pod, skipping"
      end
    else
      puts "Failed to find podspec for #{name}, skipping".blue
    end   
  end
  
  replace_paths.uniq!

  source_map_lines = replace_paths.flat_map { |t| ["# <pb:#{base_path}>\n", "settings append target.source-map '#{t.split(",").first}' '#{t.split(",").last}'\n"] }
  rewrite_lldinit(lldbinit_path, source_map_lines, base_path, app_podfile_content, podfile_restore_content)
  
  puts "\n\nšŸŽ‰ done!\n".green
  return 0
end

.find_podspec_path_for(name, podspec_paths, podspec_contents) ⇒ Object



101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# File 'lib/pod_builder/command/update_lldbinit.rb', line 101

def self.find_podspec_path_for(name, podspec_paths, podspec_contents)
  if (path = podspec_paths.detect { |t| File.basename(t, ".podspec") == name.gsub("_", "-") })
    return path
  elsif (path_index = podspec_contents.find_index { |t| t.include?(".module_name='#{name}'") })
    return podspec_paths[path_index]
  elsif (path_index = podspec_contents.find_index { |t| t.include?(".name='#{name}") }) # kind of optimistic,, but a last resort
    return podspec_paths[path_index]
  elsif (path_index = podspec_contents.find_index { |t| t.include?("'module_name':'#{name}'") }) # [json podspec]
    return podspec_paths[path_index]
  elsif (path_index = podspec_contents.find_index { |t| t.include?("'name':'#{name}") }) # [json podspec] kind of optimistic,, but a last resort
    return podspec_paths[path_index]
  else
    return nil
  end
end

.is_development_pod(podspec_path, app_podfile_content) ⇒ Object



95
96
97
98
99
# File 'lib/pod_builder/command/update_lldbinit.rb', line 95

def self.is_development_pod(podspec_path, app_podfile_content)
  development_path = Pathname.new(podspec_path).relative_path_from(Pathname.new(PodBuilder::project_path)).parent.to_s

  return app_podfile_content.include?(":path => '#{development_path}'")
end

.podfiles_status_hash(app_podfile_content, podfile_restore_content) ⇒ Object



117
118
119
120
121
122
# File 'lib/pod_builder/command/update_lldbinit.rb', line 117

def self.podfiles_status_hash(app_podfile_content, podfile_restore_content)
  # Change to either Podfile.restore (which presumely mean new prebuilds done)
  # or app's Podfile (which my occurr when pods are switched to development pod)
  # should force a regeneration of the status identifier
  Digest::MD5.hexdigest(podfile_restore_content + app_podfile_content)
end

.rewrite_lldinit(lldbinit_path, source_map_lines, base_path, app_podfile_content, podfile_restore_content) ⇒ Object



124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
# File 'lib/pod_builder/command/update_lldbinit.rb', line 124

def self.rewrite_lldinit(lldbinit_path, source_map_lines, base_path, app_podfile_content, podfile_restore_content)
  puts "Writing #{lldbinit_path}".yellow

  FileUtils.touch(lldbinit_path)
  raise "\n\nDestination file should be a file" unless File.exists?(lldbinit_path)

  lldbinit_lines = []
  skipNext = false
  File.read(lldbinit_path).each_line do |line|
    if line.include?("# <pb:#{base_path}>") || line.include?("# <pb>")
      skipNext = true
      next
    elsif skipNext
      skipNext = false
      next
    elsif line != "\n"
      if line.include?("settings set target.source-map")
        raise "\n\n#{lldbinit_destination_path} already includes a manual `settings set target.source-map`. This is unsupported and you'll have to manually remove that entry\n"
      end
      lldbinit_lines.push(line)
    end
  end

  status_hash = podfiles_status_hash(app_podfile_content, podfile_restore_content)

  source_map_lines.insert(0, "# <pb>\n")
  source_map_lines.insert(1, "settings clear target.source-map\n")
  source_map_lines.insert(2, "# <pb:#{base_path}>\n")
  source_map_lines.insert(3, "# <pb_md5:#{base_path}:#{status_hash}>\n")

  lldbinit_lines += source_map_lines

  File.write(lldbinit_path, lldbinit_lines.join())
end