lib/teapot/command/fetch.rb in teapot-2.0.0.pre.rc2 vs lib/teapot/command/fetch.rb in teapot-2.0.0.pre.rc3

- old
+ new

@@ -17,14 +17,24 @@ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. require 'samovar' + require 'rugged' module Teapot module Command + class FetchError < StandardError + def initialize(package, message) + super(message) + @package = package + end + + attr :package + end + class Fetch < Samovar::Command self.description = "Fetch remote packages according to the specified configuration." # 3 typical use cases: # - fetch current packages according to lockfile @@ -49,11 +59,11 @@ while true configuration.packages.each do |package| next if resolved.include? package # If specific packages were listed, limit updates to them. - if @packages.empty? || @packages.include?(package.name) + if @packages.nil? || @packages.empty? || @packages.include?(package.name) fetch_package(context, configuration, package, logger, **@options) end # We are done with this package, don't try to process it again: resolved << package @@ -118,30 +128,58 @@ if base_uri.scheme == nil || base_uri.scheme == 'file' base_uri = URI "file://" + File.expand_path(base_uri.path, context.root) + "/" end - branch = package.options.fetch(:branch, 'master') + branch_name = package.options.fetch(:branch, 'master') if package_lock logger.info "Package locked to commit: #{package_lock[:branch]}/#{package_lock[:commit]}" - branch = package_lock[:branch] + branch_name = package_lock[:branch] + commit_id = package_lock[:commit] end - commit = package_lock ? package_lock[:commit] : nil - if destination_path.exist? logger.info "Updating package at path #{destination_path}...".color(:cyan) repository = Rugged::Repository.new(destination_path.to_s) - repository.checkout(commit || 'origin/master') + + # Are there uncommitted changes in the work tree? + if repository.to_enum(:status).any? + raise FetchError.new(package, "Uncommited local modifications") + end + + repository.fetch('origin') + repository.checkout(branch_name) + + # Essentially implement git pull: + if commit_id + # Lookup the named branch: + branch = repository.branches[branch_name].resolve + else + # Lookup the current branch and upstream commit: + branch = repository.branches[repository.head.name] + commit_id = branch.upstream.target_id + end + + # Reset it to the requested commit if required: + repository.reset(commit_id, :hard) else logger.info "Cloning package at path #{destination_path}...".color(:cyan) external_url = package.external_url(context.root) - repository = Rugged::Repository.clone_at(external_url.to_s, destination_path.to_s, checkout_branch: branch) - repository.checkout(commit) if commit + + # Clone the repository with the specified branch: + repository = Rugged::Repository.clone_at(external_url.to_s, destination_path.to_s, checkout_branch: branch_name) + + # Reset it to the requested commit if required: + repository.reset(commit_id, :hard) if commit_id + end + + # Rugged currently doesn't have good (any?) support for submodules, so we diretly invoke git here: + if repository.submodules.any? + system("git", "submodule", "update", "--init", "--recursive", chdir: package.path) end end def fetch_package(context, configuration, package, logger, update: false, local: false) if package.local?