Skip to content

Commit

Permalink
feat: add all remotes supported by cocoapods-downloader
Browse files Browse the repository at this point in the history
  • Loading branch information
soumyamahunt committed Mar 7, 2022
1 parent 4ddd83b commit e01ea82
Show file tree
Hide file tree
Showing 12 changed files with 384 additions and 112 deletions.
3 changes: 3 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ PATH
remote: .
specs:
cocoapods-embed-flutter (0.0.1)
cocoapods
fileutils
yaml

GEM
Expand Down Expand Up @@ -66,6 +68,7 @@ GEM
ethon (0.15.0)
ffi (>= 1.15.0)
ffi (1.15.5)
fileutils (1.6.0)
fourflusher (2.3.1)
fuzzy_match (2.0.4)
gh_inspector (1.1.3)
Expand Down
2 changes: 2 additions & 0 deletions cocoapods-embed-flutter.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ Gem::Specification.new do |spec|
spec.require_paths = ['lib']

spec.add_dependency 'yaml'
spec.add_dependency 'fileutils'
spec.add_dependency 'cocoapods'

spec.add_development_dependency 'bundler'
spec.add_development_dependency 'rake'
Expand Down
3 changes: 3 additions & 0 deletions example/ios_app/Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ PATH
remote: ../..
specs:
cocoapods-embed-flutter (0.0.1)
cocoapods
fileutils
yaml

GEM
Expand Down Expand Up @@ -65,6 +67,7 @@ GEM
ethon (0.15.0)
ffi (>= 1.15.0)
ffi (1.15.5)
fileutils (1.1.0)
fourflusher (2.3.1)
fuzzy_match (2.0.4)
gh_inspector (1.1.3)
Expand Down
2 changes: 1 addition & 1 deletion example/ios_app/Podfile
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@ target 'ios_app' do
use_frameworks!

# Pods for ios_app
flutter_module 'flutter_module', :path => '../'
pub 'flutter_module', :path => '../'
end
2 changes: 1 addition & 1 deletion example/ios_app/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,6 @@ SPEC CHECKSUMS:
flutter_module: d1e1ff44505640bd9aa37f23f63380c646272be4
FlutterPluginRegistrant: 2afd5ea46d3a949472c9b7da6462d8fbf7d8b16e

PODFILE CHECKSUM: c3b3a9549c635bdd7321f4b209b67310a97803e9
PODFILE CHECKSUM: 63b6421f4bf00554065d89d2308ed2deb78332fc

COCOAPODS: 1.11.2
56 changes: 29 additions & 27 deletions lib/cocoapods-embed-flutter/flutter/dependency.rb
Original file line number Diff line number Diff line change
@@ -1,40 +1,42 @@
require 'cocoapods-embed-flutter/flutter/pubspec'

module Flutter
class Dependency
attr_reader :name, :requirements, :parent_spec, :is_dev_dependency
module Pub
class Dependency
attr_reader :name, :requirements, :parent_spec, :is_dev_dependency

def initialize(name, requirements, parent_spec, dev_dependency = false)
raise StandardError, 'A flutter dependency requires a name.' unless name
raise StandardError, 'A flutter dependency requires a parent pubspec.' unless parent_spec.is_a?(Flutter::PubSpec)
@name = name
@requirements = requirements
@parent_spec = parent_spec
@is_dev_dependency = dev_dependency
end
def initialize(name, requirements, parent_spec, dev_dependency = false)
raise StandardError, 'A flutter dependency requires a name.' unless name
raise StandardError, 'A flutter dependency requires a parent pubspec.' unless parent_spec.is_a?(Flutter::Pub::Spec)
@name = name
@requirements = requirements
@parent_spec = parent_spec
@is_dev_dependency = dev_dependency
end

def self.create_from_hash(hash, parent_spec, dev_dependency = false)
raise StandardError, 'A flutter dependency requires a parent pubspec.' unless parent_spec.is_a?(Flutter::PubSpec)
hash.keys.map { |key| Flutter::Dependency.new(key, hash[key], parent_spec, dev_dependency) }
end
def self.create_from_hash(hash, parent_spec, dev_dependency = false)
raise StandardError, 'A flutter dependency requires a parent pubspec.' unless parent_spec.is_a?(Flutter::Pub::Spec)
hash.keys.map { |key| Dependency.new(key, hash[key], parent_spec, dev_dependency) }
end

def is_local
requirements.is_a?(Hash) && requirements.include?('path')
end
def local?
requirements.is_a?(Hash) && requirements.include?('path')
end

def spec
Flutter::PubSpec.new(File.expand_path(path, File.dirname(parent_spec.file_path)))
end
def spec
Spec.find(name, File.expand_path(path, File.dirname(parent_spec.defined_in_file)))
end

def install
spec.setup if is_local
end
def install
spec.setup if local?
end

def method_missing(m, *args, &block)
if requirements.is_a?(Hash) && requirements.include?(m.to_s)
return requirements[m.to_s]
def method_missing(m, *args, &block)
if requirements.is_a?(Hash) && requirements.include?(m.to_s)
return requirements[m.to_s]
end
super.method_missing(m, *args, &block)
end
super.method_missing(m, *args, &block)
end
end
end
59 changes: 59 additions & 0 deletions lib/cocoapods-embed-flutter/flutter/downloader.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
require 'cocoapods'
require 'fileutils'

module Flutter
module Pub
module Downloader
# Downloads a package from the given `request` to the given `target` location.
#
# @return [Response] The download response for this download.
#
# @param [Request] request
# the request that describes this pod download.
#
# @param [Pathname,Nil] target
# the location to which this pod should be downloaded. If `nil`,
# then the pod will only be cached.
#
# @param [Boolean] can_cache
# whether caching is allowed.
#
# @param [Pathname,Nil] cache_path
# the path used to cache pod downloads.
#
def self.download(
request,
target,
can_cache: true,
cache_path: Pod::Config.instance.cache_root + 'Pods'
)
can_cache &&= !Pod::Config.instance.skip_download_cache

request = Pod::Downloader.preprocess_request(request)

# if can_cache
# raise ArgumentError, 'Must provide a `cache_path` when caching.' unless cache_path
# cache = Pod::Downloader::Cache.new(cache_path)
# result = cache.download_pod(request)
# else
# raise ArgumentError, 'Must provide a `target` when caching is disabled.' unless target

# result, = Pod::Downloader.download_request(request, target)
# Pod::Installer::PodSourcePreparer.new(result.spec, result.location).prepare!
# end
raise ArgumentError, 'Must provide a `target` when caching is disabled.' unless target
result, = Pod::Downloader.download_request(request, target)

if target && result.location && target != result.location
Pod::UI.message "Copying #{request.name} from `#{result.location}` to #{UI.path target}", '> ' do
Pod::Downloader::Cache.read_lock(result.location) do
FileUtils.rm_rf target
FileUtils.cp_r(result.location, target)
end
end
end
result
end
end
end
end
187 changes: 187 additions & 0 deletions lib/cocoapods-embed-flutter/flutter/external_sources.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
# Similar to:
# https://github.com/CocoaPods/CocoaPods/blob/master/lib/cocoapods/external_sources/abstract_external_source.rb
require 'cocoapods-embed-flutter/flutter/downloader'
require 'cocoapods'

module Flutter
module Pub
module ExternalSources
SOURCE_KEYS = {
:git => [:tag, :branch, :commit, :submodules].freeze,
:svn => [:folder, :tag, :revision].freeze,
:hg => [:revision].freeze,
:http => [:flatten, :type, :sha256, :sha1, :headers].freeze,
}.freeze

def self.fetchWithNameAndOptions(name, options)
raise StandardError, 'A flutter module requires a name.' unless name

options = options.last if options.is_a?(Array)
raise StandardError, "No options specified for flutter module: '#{name}'." unless options.is_a?(Hash)

if options.key?(:path)
path = options[:path]
elsif SOURCE_KEYS.keys.any? { |key| options.key?(key) }
source = DownloaderSource.new(name, options, Pod::Config.instance.podfile_path)
source.fetch(Pod::Config.instance.sandbox)
path = source.normalized_pupspec_path
else
raise StandardError, "Invalid flutter module: '#{name}'."
end

return Spec.find(name, path)
end

# Provides support for fetching a specification file from a source handled
# by the downloader. Supports all the options of the downloader
#
# @note The pubspec must be in the root of the repository
# or in directory with the name provided
#
class DownloaderSource
# @return [String] the name of the Package described by this external source.
#
attr_reader :name

# @return [Hash{Symbol => String}] the hash representation of the
# external source.
#
attr_reader :params

# @return [String] the path where the podfile is defined to resolve
# relative paths.
#
attr_reader :podfile_path

# @return [Boolean] Whether the source is allowed to touch the cache.
#
attr_reader :can_cache
alias_method :can_cache?, :can_cache

# Initialize a new instance
#
# @param [String] name @see #name
# @param [Hash] params @see #params
# @param [String] podfile_path @see #podfile_path
# @param [Boolean] can_cache @see #can_cache
#
def initialize(name, params, podfile_path, can_cache = true)
@name = name
@params = params
@podfile_path = podfile_path
@can_cache = can_cache
end

# @return [Boolean] whether an external source source is equal to another
# according to the {#name} and to the {#params}.
#
def ==(other)
return false if other.nil?
name == other.name && params == other.params
end


public

# @!group Subclasses hooks

# Fetches the external source from the remote according to the params.
#
# @param [Sandbox] sandbox
# the sandbox where the specification should be stored.
#
# @return [void]
#
def fetch(sandbox)
pre_download(sandbox)
end

# @return [String] a string representation of the source suitable for UI.
#
def description
strategy = Pod::Downloader.strategy_from_options(params)
options = params.dup
url = options.delete(strategy)
result = "from `#{url}`"
options.each do |key, value|
result << ", #{key} `#{value}`"
end
result
end

# Return the normalized path for a pubspec for a relative declared path.
#
# @param [String] declared_path
# The path declared in the podfile.
#
# @return [String] The uri of the pubspec appending the name of the file
# and expanding it if necessary.
#
# @note If the declared path is expanded only if the represents a path
# relative to the file system.
#
def normalized_pupspec_path(declared_path)
Spec.find_file(name, declared_path)
end

def normalized_pupspec_path
Spec.find_file(name, target)
end

private

# @! Subclasses helpers

# Pre-downloads a Pod passing the options to the downloader and informing
# the sandbox.
#
# @param [Sandbox] sandbox
# The sandbox where the Pod should be downloaded.
#
# @note To prevent a double download of the repository the pod is
# marked as pre-downloaded indicating to the installer that only
# clean operations are needed.
#
# @todo The downloader configuration is the same of the
# #{PodSourceInstaller} and it needs to be kept in sync.
#
# @return [void]
#
def pre_download(sandbox)
title = "Pre-downloading: `#{name}` #{description}"
Pod::UI.titled_section(title, :verbose_prefix => '-> ') do
begin
download_result = Downloader.download(download_request, target, :can_cache => can_cache)
rescue Pod::DSLError => e
raise Pod::Informative, "Failed to load '#{name}' pubspec: #{e.message}"
rescue => e
raise Pod::Informative, "Failed to download '#{name}': #{e.message}"
end

# spec = download_result.spec
# raise Pod::Informative, "Unable to find a specification for '#{name}'." unless spec

# since the podspec might be cleaned, we want the checksum to refer
# to the json in the sandbox
# spec.defined_in_file = nil

# store_podspec(sandbox, spec)
# sandbox.store_pre_downloaded_pod(name)
# sandbox.store_checkout_source(name, download_result.checkout_options)
end
end

def download_request
Pod::Downloader::Request.new(
:name => name,
:params => params,
)
end

def target
return Pod::Config.instance.sandbox.pod_dir(name)
end
end
end
end
end
Loading

0 comments on commit e01ea82

Please sign in to comment.