fortinmike/git-multirepo

View on GitHub
lib/multirepo/commands/do-command.rb

Summary

Maintainability
A
0 mins
Test Coverage
require_relative "command"
require "multirepo/utility/console"
require "multirepo/utility/utils"
require "multirepo/files/config-file"
require "multirepo/git/repo"
require "multirepo/git/git-runner"
require "multirepo/logic/performer"
require "multirepo/logic/repo-selection"

module MultiRepo
  class DoCommand < Command
    self.command = "do"
    self.summary = "Perform an arbitrary Git operation in the main repository, dependency repositories or all repositories."

    def self.options
      [
        ['"<operation>"', 'The git command to perform, between quotes, omitting the executable name (ex: "reset --hard HEAD")'],
        ['[--main]', 'Perform the operation in the main repository only.'],
        ['[--deps]', 'Perform the operation in dependencies only.'],
        ['[--all]', 'Perform the operation in the main repository and all dependencies.']
      ].concat(super)
    end
    
    def initialize(argv)
      @operation = argv.remainder!.join(" ")
      @repo_selection = RepoSelection.new(argv)
      super
    end

    def validate!
      help! "You must provide a git operation to perform" unless @operation
      help! "You can't provide more than one operation modifier (--deps, --main, etc.)" unless @repo_selection.valid?
    end
    
    def run
      ensure_in_work_tree
      ensure_multirepo_enabled

      @operation = @operation.sub(/^git /, "")
      
      success = true
      case @repo_selection.value
      when RepoSelection::MAIN
        confirm_main_repo_operation
        success &= perform_operation_on_main(@operation)
      when RepoSelection::DEPS
        confirm_dependencies_operation
        success &= perform_operation_on_dependencies(@operation)
      when RepoSelection::ALL
        confirm_main_repo_operation
        confirm_dependencies_operation
        success &= perform_operation_on_dependencies(@operation) # Ordered dependencies first
        success &= perform_operation_on_main(@operation) # Main last
      end
      
      Console.log_warning("Some operations finished with non-zero exit status. Please review the above.") unless success
    end
    
    def perform_operation_on_main(operation)
      perform_operation(".", operation)
    end

    def perform_operation_on_dependencies(operation)
      success = true
      Performer.depth_ordered_dependencies.each do |dependency|
        success &= perform_operation(dependency.config_entry.repo.path, operation)
      end
      return success
    end

    def perform_operation(path, operation)
      Console.log_step("Performing operation on '#{path}'")
      GitRunner.run_as_system(path, operation)
      GitRunner.last_command_succeeded
    end
    
    def confirm_main_repo_operation
      unless main_repo_clean?
        Console.log_warning("Main repo contains uncommitted changes")
        fail MultiRepoException, "Aborted" unless Console.ask("Proceed anyway?")
      end
    end
    
    def confirm_dependencies_operation
      unless dependencies_clean?
        Console.log_warning("Some dependencies contain uncommitted changes")
        fail MultiRepoException, "Aborted" unless Console.ask("Proceed anyway?")
      end
    end
    
    def main_repo_clean?
      Repo.new(".").clean?
    end
    
    def dependencies_clean?
      config_entries = ConfigFile.new(".").load_entries
      return Utils.dependencies_clean?(config_entries)
    end
  end
end