lib/teapot/controller/fetch.rb in teapot-1.1.2 vs lib/teapot/controller/fetch.rb in teapot-1.2.0

- old
+ new

@@ -21,21 +21,20 @@ require_relative '../controller' require_relative '../repository' module Teapot class Controller - def fetch + def fetch(**options) resolved = Set.new configuration = context.configuration unresolved = context.unresolved(configuration.packages) - tries = 0 - while tries < @options[:maximum_fetch_depth] + while true configuration.packages.each do |package| next if resolved.include? package - fetch_package(context, configuration, package) + fetch_package(context, configuration, package, **options) # We are done with this package, don't try to process it again: resolved << package end @@ -47,12 +46,10 @@ # No additional packages were resolved, we have reached a fixed point: if previously_unresolved == unresolved || unresolved.count == 0 break end - - tries += 1 end if unresolved.count > 0 log "Could not fetch all packages!".color(:red) unresolved.each do |package| @@ -64,80 +61,111 @@ end private def current_commit(package) - IO.popen(['git', '--git-dir', (package.path + ".git").to_s, 'rev-parse', '--verify', 'HEAD']) do |io| + IO.popen(['git', '--git-dir', (package.path + '.git').to_s, 'rev-parse', '--verify', 'HEAD']) do |io| io.read.chomp! end end - - def fetch_package(context, configuration, package) - destination_path = package.path - lock_store = configuration.lock_store - if package.local? - log "Linking local #{package}...".color(:cyan) + def current_branch(package) + IO.popen(['git', '--git-dir', (package.path + '.git').to_s, 'rev-parse', '--abbrev-ref', 'HEAD']) do |io| + io.read.chomp! + end + end - local_path = context.root + package.options[:local] + def current_metadata(package) + { + branch: current_branch(package), + commit: current_commit(package) + } + end + + def link_local_package(context, configuration, package) + log "Linking local #{package}...".color(:cyan) - # Make the top level directory if required: - destination_path.dirname.create - - unless destination_path.exist? - destination_path.make_symlink(local_path) - end - elsif package.external? - package_lock = nil - - unless @options[:unlock] - package_lock = lock_store.transaction(true){|store| store[package.name]} - end + local_path = context.root + package.options[:local] - log "Fetching #{package}...".color(:cyan) + # Where we are going to put the package: + destination_path = package.path - base_uri = URI(package.options[:source].to_s) + # Make the top level directory if required: + destination_path.dirname.create - if base_uri.scheme == nil || base_uri.scheme == 'file' - base_uri = URI "file://" + File.expand_path(base_uri.path, context.root) + "/" - end + unless destination_path.exist? + destination_path.make_symlink(local_path) + end + end - branch = package.options.fetch(:version, 'master') + def clone_or_pull_package(context, configuration, package, package_lock) + log "Fetching #{package}...".color(:cyan) - if package_lock - log "Package locked to commit: #{package_lock[:branch]}/#{package_lock[:commit]}" + # Where we are going to put the package: + destination_path = package.path - branch = package_lock[:branch] - end + base_uri = URI(package.options[:source].to_s) - commit = package_lock ? package_lock[:commit] : nil + if base_uri.scheme == nil || base_uri.scheme == 'file' + base_uri = URI "file://" + File.expand_path(base_uri.path, context.root) + "/" + end - unless destination_path.exist? - log "Cloning package at path #{destination_path} ...".color(:cyan) - - begin - external_url = package.external_url(context.root) + branch = package.options.fetch(:branch, 'master') - Repository.new(destination_path).clone!(external_url, branch, commit) - rescue - log "Failed to clone #{external_url}...".color(:red) + if package_lock + log "Package locked to commit: #{package_lock[:branch]}/#{package_lock[:commit]}" - raise - end - else - log "Updating package at path #{destination_path} ...".color(:cyan) + branch = package_lock[:branch] + end - commit = package_lock ? package_lock[:commit] : nil - Repository.new(destination_path).update(branch, commit) + commit = package_lock ? package_lock[:commit] : nil + + unless destination_path.exist? + log "Cloning package at path #{destination_path} ...".color(:cyan) + + begin + external_url = package.external_url(context.root) + + Repository.new(destination_path).clone!(external_url, branch, commit) + rescue + log "Failed to clone #{external_url}...".color(:red) + + raise end + else + log "Updating package at path #{destination_path} ...".color(:cyan) + + commit = package_lock ? package_lock[:commit] : nil + Repository.new(destination_path).update(branch, commit) + end + end + + def fetch_package(context, configuration, package, update: false, local: false) + if package.local? + link_local_package(context, configuration, package) + elsif package.external? + lock_store = configuration.lock_store + # If we are updating, don't bother reading the current branch/commit details. + unless update + package_lock = lock_store.transaction(true){|store| store[package.name]} + end + + unless local + clone_or_pull_package(context, configuration, package, package_lock) + end + # Lock the package, unless it was already locked: unless package_lock + metadata = current_metadata(package) + lock_store.transaction do |store| - store[package.name] = { - :branch => branch, - :commit => current_commit(package) - } + store_metadata = store[package.name] + + if store_metadata.nil? or store_metadata[:commit] != metadata[:commit] + log("Updating lockfile for package #{package.name}: #{metadata[:commit]}...") + store[package.name] = metadata + end end end end end end