flaviogranero/assisted_workflow

View on GitHub
lib/assisted_workflow/addons/git.rb

Summary

Maintainability
A
0 mins
Test Coverage
require "assisted_workflow/exceptions"
require "assisted_workflow/addons/base"

module AssistedWorkflow::Addons
  
  class GitError < AssistedWorkflow::Error; end
  
  class Git < Base
    
    DESCRIPTION_LIMIT = 30
    
    def initialize(output, options = {})
      super
      @command_options = {:raise_error => true}.merge(options)
    end
    
    # creates a new git branch based on story attributes
    # the branch name format is:
    # => story_onwer_username.story_id.story_name
    def create_story_branch(story)
      log "creating the feature branch"
      branch = branch_name(story)
      git "checkout -b #{branch}"
      # git "push --set-upstream origin #{branch}"
    end
    
    # run all the git steps required for a clean pull request
    def rebase_and_push
      log "preparing local branch"
      check_everything_commited!
      branch = current_branch
      git "checkout master"
      git "pull --rebase"
      git "checkout #{branch}"
      git "rebase master"
      git "push -u -f origin #{branch}"
    end
    
    # returns the current story id based on branch name
    def current_story_id
      current_branch.split(".")[1]
    end
    
    # returns the current local branch name
    def current_branch
      git("rev-parse --abbrev-ref HEAD", :silent => true)
    end
    
    # returns the repository name assigned to origin following the format:
    # owner/project
    def repository
      url = git("config --get remote.origin.url", :error => "cannot find 'origin' remote repository url")
      url.gsub("git@github.com:", "").gsub("https://github.com/", "").gsub(/\.git$/, "").chomp
    end
    
    # check if current branch is merged into master
    def check_merged!
      check_everything_commited!
      branch = current_branch
      git "checkout master"
      git "pull --rebase"
      merged = git("branch --merged").include?(branch)
      git "checkout #{branch}"
      unless merged
        raise AssistedWorkflow::Error, "this branch is not merged into master"
      end
      merged
    end
    
    # removes current branch and its remote version
    def remove_branch
      log "removing local and remote feature branches"
      branch = current_branch
      git "push origin :#{branch}", :raise_error => false
      git "checkout master"
      git "branch -D #{branch}"
    end
    
    private #=================================================================
    
    def git(command, options = {})
      options = @command_options.merge(options)
      puts "git #{command}" unless options[:silent] == true
      result = system("git #{command}")
      if system_error? && options[:raise_error]
        msg = ["git command error", options[:error]].compact.join(": ")
        raise GitError, msg
      end
      result
    end
    
    def system(command)
      %x{#{command}}.chomp
    end
    
    def system_error?
      $? != 0
    end
    
    def branch_name(story)
      description = story.name.to_s.downcase.gsub(/\W/, "_").slice(0, DESCRIPTION_LIMIT)
      [story.other_id, story.id, description].join(".").downcase
    end
    
    def not_commited_changes
      git("status --porcelain", :silent => true).split("\n")
    end
    
    def check_everything_commited!
      raise AssistedWorkflow::Error, "git: there are not commited changes" unless not_commited_changes.empty?
    end
  end
end