arpm 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
 - data/.gitignore +23 -0
 - data/Gemfile +4 -0
 - data/LICENSE.txt +22 -0
 - data/README.md +92 -0
 - data/Rakefile +2 -0
 - data/arpm.gemspec +27 -0
 - data/bin/arpm +6 -0
 - data/lib/arpm.rb +14 -0
 - data/lib/arpm/cli.rb +250 -0
 - data/lib/arpm/config.rb +16 -0
 - data/lib/arpm/libfile.rb +33 -0
 - data/lib/arpm/list.rb +106 -0
 - data/lib/arpm/os.rb +17 -0
 - data/lib/arpm/package.rb +120 -0
 - data/lib/arpm/string.rb +24 -0
 - data/lib/arpm/vendor/ruby-git/git.rb +148 -0
 - data/lib/arpm/vendor/ruby-git/git/author.rb +14 -0
 - data/lib/arpm/vendor/ruby-git/git/base.rb +560 -0
 - data/lib/arpm/vendor/ruby-git/git/branch.rb +122 -0
 - data/lib/arpm/vendor/ruby-git/git/branches.rb +71 -0
 - data/lib/arpm/vendor/ruby-git/git/diff.rb +146 -0
 - data/lib/arpm/vendor/ruby-git/git/index.rb +5 -0
 - data/lib/arpm/vendor/ruby-git/git/lib.rb +848 -0
 - data/lib/arpm/vendor/ruby-git/git/log.rb +128 -0
 - data/lib/arpm/vendor/ruby-git/git/object.rb +282 -0
 - data/lib/arpm/vendor/ruby-git/git/path.rb +31 -0
 - data/lib/arpm/vendor/ruby-git/git/remote.rb +36 -0
 - data/lib/arpm/vendor/ruby-git/git/repository.rb +6 -0
 - data/lib/arpm/vendor/ruby-git/git/stash.rb +27 -0
 - data/lib/arpm/vendor/ruby-git/git/stashes.rb +44 -0
 - data/lib/arpm/vendor/ruby-git/git/status.rb +117 -0
 - data/lib/arpm/vendor/ruby-git/git/version.rb +7 -0
 - data/lib/arpm/vendor/ruby-git/git/working_directory.rb +4 -0
 - data/lib/arpm/version.rb +3 -0
 - data/packages.json +8 -0
 - metadata +122 -0
 
| 
         @@ -0,0 +1,122 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'git/path'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module Git
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
              class Branch < Path
         
     | 
| 
      
 6 
     | 
    
         
            +
                
         
     | 
| 
      
 7 
     | 
    
         
            +
                attr_accessor :full, :remote, :name
         
     | 
| 
      
 8 
     | 
    
         
            +
                
         
     | 
| 
      
 9 
     | 
    
         
            +
                def initialize(base, name)
         
     | 
| 
      
 10 
     | 
    
         
            +
                  @full = name
         
     | 
| 
      
 11 
     | 
    
         
            +
                  @base = base
         
     | 
| 
      
 12 
     | 
    
         
            +
                  @gcommit = nil
         
     | 
| 
      
 13 
     | 
    
         
            +
                  @stashes = nil
         
     | 
| 
      
 14 
     | 
    
         
            +
                  @remote, @name = parse_name(name)
         
     | 
| 
      
 15 
     | 
    
         
            +
                end
         
     | 
| 
      
 16 
     | 
    
         
            +
                
         
     | 
| 
      
 17 
     | 
    
         
            +
                def gcommit
         
     | 
| 
      
 18 
     | 
    
         
            +
                  @gcommit ||= @base.gcommit(@full)
         
     | 
| 
      
 19 
     | 
    
         
            +
                  @gcommit
         
     | 
| 
      
 20 
     | 
    
         
            +
                end
         
     | 
| 
      
 21 
     | 
    
         
            +
                
         
     | 
| 
      
 22 
     | 
    
         
            +
                def stashes
         
     | 
| 
      
 23 
     | 
    
         
            +
                  @stashes ||= Git::Stashes.new(@base)
         
     | 
| 
      
 24 
     | 
    
         
            +
                end
         
     | 
| 
      
 25 
     | 
    
         
            +
                
         
     | 
| 
      
 26 
     | 
    
         
            +
                def checkout
         
     | 
| 
      
 27 
     | 
    
         
            +
                  check_if_create
         
     | 
| 
      
 28 
     | 
    
         
            +
                  @base.checkout(@full)
         
     | 
| 
      
 29 
     | 
    
         
            +
                end
         
     | 
| 
      
 30 
     | 
    
         
            +
                
         
     | 
| 
      
 31 
     | 
    
         
            +
                def archive(file, opts = {})
         
     | 
| 
      
 32 
     | 
    
         
            +
                  @base.lib.archive(@full, file, opts)
         
     | 
| 
      
 33 
     | 
    
         
            +
                end
         
     | 
| 
      
 34 
     | 
    
         
            +
                
         
     | 
| 
      
 35 
     | 
    
         
            +
                # g.branch('new_branch').in_branch do
         
     | 
| 
      
 36 
     | 
    
         
            +
                #   # create new file
         
     | 
| 
      
 37 
     | 
    
         
            +
                #   # do other stuff
         
     | 
| 
      
 38 
     | 
    
         
            +
                #   return true # auto commits and switches back
         
     | 
| 
      
 39 
     | 
    
         
            +
                # end
         
     | 
| 
      
 40 
     | 
    
         
            +
                def in_branch (message = 'in branch work')
         
     | 
| 
      
 41 
     | 
    
         
            +
                  old_current = @base.lib.branch_current
         
     | 
| 
      
 42 
     | 
    
         
            +
                  checkout
         
     | 
| 
      
 43 
     | 
    
         
            +
                  if yield
         
     | 
| 
      
 44 
     | 
    
         
            +
                    @base.commit_all(message)
         
     | 
| 
      
 45 
     | 
    
         
            +
                  else
         
     | 
| 
      
 46 
     | 
    
         
            +
                    @base.reset_hard
         
     | 
| 
      
 47 
     | 
    
         
            +
                  end
         
     | 
| 
      
 48 
     | 
    
         
            +
                  @base.checkout(old_current)
         
     | 
| 
      
 49 
     | 
    
         
            +
                end
         
     | 
| 
      
 50 
     | 
    
         
            +
                
         
     | 
| 
      
 51 
     | 
    
         
            +
                def create
         
     | 
| 
      
 52 
     | 
    
         
            +
                  check_if_create
         
     | 
| 
      
 53 
     | 
    
         
            +
                end
         
     | 
| 
      
 54 
     | 
    
         
            +
                
         
     | 
| 
      
 55 
     | 
    
         
            +
                def delete
         
     | 
| 
      
 56 
     | 
    
         
            +
                  @base.lib.branch_delete(@name)
         
     | 
| 
      
 57 
     | 
    
         
            +
                end
         
     | 
| 
      
 58 
     | 
    
         
            +
                
         
     | 
| 
      
 59 
     | 
    
         
            +
                def current
         
     | 
| 
      
 60 
     | 
    
         
            +
                  determine_current
         
     | 
| 
      
 61 
     | 
    
         
            +
                end
         
     | 
| 
      
 62 
     | 
    
         
            +
                
         
     | 
| 
      
 63 
     | 
    
         
            +
                def merge(branch = nil, message = nil)
         
     | 
| 
      
 64 
     | 
    
         
            +
                  if branch
         
     | 
| 
      
 65 
     | 
    
         
            +
                    in_branch do 
         
     | 
| 
      
 66 
     | 
    
         
            +
                      @base.merge(branch, message)
         
     | 
| 
      
 67 
     | 
    
         
            +
                      false
         
     | 
| 
      
 68 
     | 
    
         
            +
                    end
         
     | 
| 
      
 69 
     | 
    
         
            +
                    # merge a branch into this one
         
     | 
| 
      
 70 
     | 
    
         
            +
                  else
         
     | 
| 
      
 71 
     | 
    
         
            +
                    # merge this branch into the current one
         
     | 
| 
      
 72 
     | 
    
         
            +
                    @base.merge(@name)
         
     | 
| 
      
 73 
     | 
    
         
            +
                  end
         
     | 
| 
      
 74 
     | 
    
         
            +
                end
         
     | 
| 
      
 75 
     | 
    
         
            +
                
         
     | 
| 
      
 76 
     | 
    
         
            +
                def update_ref(commit)
         
     | 
| 
      
 77 
     | 
    
         
            +
                  @base.lib.update_ref(@full, commit)
         
     | 
| 
      
 78 
     | 
    
         
            +
                end
         
     | 
| 
      
 79 
     | 
    
         
            +
                
         
     | 
| 
      
 80 
     | 
    
         
            +
                def to_a
         
     | 
| 
      
 81 
     | 
    
         
            +
                  [@full]
         
     | 
| 
      
 82 
     | 
    
         
            +
                end
         
     | 
| 
      
 83 
     | 
    
         
            +
                
         
     | 
| 
      
 84 
     | 
    
         
            +
                def to_s
         
     | 
| 
      
 85 
     | 
    
         
            +
                  @full
         
     | 
| 
      
 86 
     | 
    
         
            +
                end
         
     | 
| 
      
 87 
     | 
    
         
            +
                
         
     | 
| 
      
 88 
     | 
    
         
            +
                private 
         
     | 
| 
      
 89 
     | 
    
         
            +
             
     | 
| 
      
 90 
     | 
    
         
            +
                  def check_if_create
         
     | 
| 
      
 91 
     | 
    
         
            +
                    @base.lib.branch_new(@name) rescue nil
         
     | 
| 
      
 92 
     | 
    
         
            +
                  end
         
     | 
| 
      
 93 
     | 
    
         
            +
                  
         
     | 
| 
      
 94 
     | 
    
         
            +
                  def determine_current
         
     | 
| 
      
 95 
     | 
    
         
            +
                    @base.lib.branch_current == @name
         
     | 
| 
      
 96 
     | 
    
         
            +
                  end
         
     | 
| 
      
 97 
     | 
    
         
            +
                
         
     | 
| 
      
 98 
     | 
    
         
            +
                  # Given a full branch name return an Array containing the remote and branch names.
         
     | 
| 
      
 99 
     | 
    
         
            +
                  #
         
     | 
| 
      
 100 
     | 
    
         
            +
                  # Removes 'remotes' from the beggining of the name (if present).
         
     | 
| 
      
 101 
     | 
    
         
            +
                  # Takes the second part (splittign by '/') as the remote name.
         
     | 
| 
      
 102 
     | 
    
         
            +
                  # Takes the rest as the repo name (can also hold one or more '/').
         
     | 
| 
      
 103 
     | 
    
         
            +
                  #
         
     | 
| 
      
 104 
     | 
    
         
            +
                  # Example:
         
     | 
| 
      
 105 
     | 
    
         
            +
                  #   parse_name('master') #=> [nil, 'master']
         
     | 
| 
      
 106 
     | 
    
         
            +
                  #   parse_name('origin/master') #=> ['origin', 'master']
         
     | 
| 
      
 107 
     | 
    
         
            +
                  #   parse_name('remotes/origin/master') #=> ['origin', 'master']
         
     | 
| 
      
 108 
     | 
    
         
            +
                  #   parse_name('origin/master/v2') #=> ['origin', 'master/v2'] 
         
     | 
| 
      
 109 
     | 
    
         
            +
                  #
         
     | 
| 
      
 110 
     | 
    
         
            +
                  # param [String] name branch full name.
         
     | 
| 
      
 111 
     | 
    
         
            +
                  # return [<Git::Remote,NilClass,String>] an Array containing the remote and branch names. 
         
     | 
| 
      
 112 
     | 
    
         
            +
                  def parse_name(name)
         
     | 
| 
      
 113 
     | 
    
         
            +
                    if name.match(/^(?:remotes)?\/([^\/]+)\/(.+)/)
         
     | 
| 
      
 114 
     | 
    
         
            +
                      return [Git::Remote.new(@base, $1), $2]
         
     | 
| 
      
 115 
     | 
    
         
            +
                    end
         
     | 
| 
      
 116 
     | 
    
         
            +
             
     | 
| 
      
 117 
     | 
    
         
            +
                    return [nil, name]
         
     | 
| 
      
 118 
     | 
    
         
            +
                  end
         
     | 
| 
      
 119 
     | 
    
         
            +
                
         
     | 
| 
      
 120 
     | 
    
         
            +
              end
         
     | 
| 
      
 121 
     | 
    
         
            +
              
         
     | 
| 
      
 122 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,71 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Git
         
     | 
| 
      
 2 
     | 
    
         
            +
              
         
     | 
| 
      
 3 
     | 
    
         
            +
              # object that holds all the available branches
         
     | 
| 
      
 4 
     | 
    
         
            +
              class Branches
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
                include Enumerable
         
     | 
| 
      
 7 
     | 
    
         
            +
                
         
     | 
| 
      
 8 
     | 
    
         
            +
                def initialize(base)
         
     | 
| 
      
 9 
     | 
    
         
            +
                  @branches = {}
         
     | 
| 
      
 10 
     | 
    
         
            +
                  
         
     | 
| 
      
 11 
     | 
    
         
            +
                  @base = base
         
     | 
| 
      
 12 
     | 
    
         
            +
                        
         
     | 
| 
      
 13 
     | 
    
         
            +
                  @base.lib.branches_all.each do |b|
         
     | 
| 
      
 14 
     | 
    
         
            +
                    @branches[b[0]] = Git::Branch.new(@base, b[0])
         
     | 
| 
      
 15 
     | 
    
         
            +
                  end
         
     | 
| 
      
 16 
     | 
    
         
            +
                end
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                def local
         
     | 
| 
      
 19 
     | 
    
         
            +
                  self.select { |b| !b.remote }
         
     | 
| 
      
 20 
     | 
    
         
            +
                end
         
     | 
| 
      
 21 
     | 
    
         
            +
                
         
     | 
| 
      
 22 
     | 
    
         
            +
                def remote
         
     | 
| 
      
 23 
     | 
    
         
            +
                  self.select { |b| b.remote }
         
     | 
| 
      
 24 
     | 
    
         
            +
                end
         
     | 
| 
      
 25 
     | 
    
         
            +
                
         
     | 
| 
      
 26 
     | 
    
         
            +
                # array like methods
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
                def size
         
     | 
| 
      
 29 
     | 
    
         
            +
                  @branches.size
         
     | 
| 
      
 30 
     | 
    
         
            +
                end    
         
     | 
| 
      
 31 
     | 
    
         
            +
                
         
     | 
| 
      
 32 
     | 
    
         
            +
                def each(&block)
         
     | 
| 
      
 33 
     | 
    
         
            +
                  @branches.values.each(&block)
         
     | 
| 
      
 34 
     | 
    
         
            +
                end
         
     | 
| 
      
 35 
     | 
    
         
            +
                
         
     | 
| 
      
 36 
     | 
    
         
            +
                # Returns the target branch
         
     | 
| 
      
 37 
     | 
    
         
            +
                #
         
     | 
| 
      
 38 
     | 
    
         
            +
                # Example:
         
     | 
| 
      
 39 
     | 
    
         
            +
                #   Given (git branch -a):
         
     | 
| 
      
 40 
     | 
    
         
            +
                #    master
         
     | 
| 
      
 41 
     | 
    
         
            +
                #    remotes/working/master
         
     | 
| 
      
 42 
     | 
    
         
            +
                #
         
     | 
| 
      
 43 
     | 
    
         
            +
                #   g.branches['master'].full #=> 'master'
         
     | 
| 
      
 44 
     | 
    
         
            +
                #   g.branches['working/master'].full => 'remotes/working/master'
         
     | 
| 
      
 45 
     | 
    
         
            +
                #   g.branches['remotes/working/master'].full => 'remotes/working/master'
         
     | 
| 
      
 46 
     | 
    
         
            +
                #
         
     | 
| 
      
 47 
     | 
    
         
            +
                # @param [#to_s] branch_name the target branch name.
         
     | 
| 
      
 48 
     | 
    
         
            +
                # @return [Git::Branch] the target branch.
         
     | 
| 
      
 49 
     | 
    
         
            +
                def [](branch_name)
         
     | 
| 
      
 50 
     | 
    
         
            +
                  @branches.values.inject(@branches) do |branches, branch|
         
     | 
| 
      
 51 
     | 
    
         
            +
                    branches[branch.full] ||= branch
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
                    # This is how Git (version 1.7.9.5) works. 
         
     | 
| 
      
 54 
     | 
    
         
            +
                    # Lets you ignore the 'remotes' if its at the beginning of the branch full name (even if is not a real remote branch). 
         
     | 
| 
      
 55 
     | 
    
         
            +
                    branches[branch.full.sub('remotes/', '')] ||= branch if branch.full =~ /^remotes\/.+/
         
     | 
| 
      
 56 
     | 
    
         
            +
                    
         
     | 
| 
      
 57 
     | 
    
         
            +
                    branches
         
     | 
| 
      
 58 
     | 
    
         
            +
                  end[branch_name.to_s]
         
     | 
| 
      
 59 
     | 
    
         
            +
                end
         
     | 
| 
      
 60 
     | 
    
         
            +
                
         
     | 
| 
      
 61 
     | 
    
         
            +
                def to_s
         
     | 
| 
      
 62 
     | 
    
         
            +
                  out = ''
         
     | 
| 
      
 63 
     | 
    
         
            +
                  @branches.each do |k, b|
         
     | 
| 
      
 64 
     | 
    
         
            +
                    out << (b.current ? '* ' : '  ') << b.to_s << "\n"
         
     | 
| 
      
 65 
     | 
    
         
            +
                  end
         
     | 
| 
      
 66 
     | 
    
         
            +
                  out
         
     | 
| 
      
 67 
     | 
    
         
            +
                end
         
     | 
| 
      
 68 
     | 
    
         
            +
                
         
     | 
| 
      
 69 
     | 
    
         
            +
              end
         
     | 
| 
      
 70 
     | 
    
         
            +
             
     | 
| 
      
 71 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,146 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Git
         
     | 
| 
      
 2 
     | 
    
         
            +
              
         
     | 
| 
      
 3 
     | 
    
         
            +
              # object that holds the last X commits on given branch
         
     | 
| 
      
 4 
     | 
    
         
            +
              class Diff
         
     | 
| 
      
 5 
     | 
    
         
            +
                include Enumerable
         
     | 
| 
      
 6 
     | 
    
         
            +
                
         
     | 
| 
      
 7 
     | 
    
         
            +
                def initialize(base, from = nil, to = nil)
         
     | 
| 
      
 8 
     | 
    
         
            +
                  @base = base
         
     | 
| 
      
 9 
     | 
    
         
            +
                  @from = from.to_s
         
     | 
| 
      
 10 
     | 
    
         
            +
                  @to = to.to_s
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                  @path = nil
         
     | 
| 
      
 13 
     | 
    
         
            +
                  @full_diff = nil
         
     | 
| 
      
 14 
     | 
    
         
            +
                  @full_diff_files = nil
         
     | 
| 
      
 15 
     | 
    
         
            +
                  @stats = nil
         
     | 
| 
      
 16 
     | 
    
         
            +
                end
         
     | 
| 
      
 17 
     | 
    
         
            +
                attr_reader :from, :to
         
     | 
| 
      
 18 
     | 
    
         
            +
                
         
     | 
| 
      
 19 
     | 
    
         
            +
                def path(path)
         
     | 
| 
      
 20 
     | 
    
         
            +
                  @path = path
         
     | 
| 
      
 21 
     | 
    
         
            +
                  return self
         
     | 
| 
      
 22 
     | 
    
         
            +
                end
         
     | 
| 
      
 23 
     | 
    
         
            +
                
         
     | 
| 
      
 24 
     | 
    
         
            +
                def size
         
     | 
| 
      
 25 
     | 
    
         
            +
                  cache_stats
         
     | 
| 
      
 26 
     | 
    
         
            +
                  @stats[:total][:files]
         
     | 
| 
      
 27 
     | 
    
         
            +
                end
         
     | 
| 
      
 28 
     | 
    
         
            +
                
         
     | 
| 
      
 29 
     | 
    
         
            +
                def lines
         
     | 
| 
      
 30 
     | 
    
         
            +
                  cache_stats
         
     | 
| 
      
 31 
     | 
    
         
            +
                  @stats[:total][:lines]
         
     | 
| 
      
 32 
     | 
    
         
            +
                end
         
     | 
| 
      
 33 
     | 
    
         
            +
                
         
     | 
| 
      
 34 
     | 
    
         
            +
                def deletions
         
     | 
| 
      
 35 
     | 
    
         
            +
                  cache_stats
         
     | 
| 
      
 36 
     | 
    
         
            +
                  @stats[:total][:deletions]
         
     | 
| 
      
 37 
     | 
    
         
            +
                end
         
     | 
| 
      
 38 
     | 
    
         
            +
                
         
     | 
| 
      
 39 
     | 
    
         
            +
                def insertions
         
     | 
| 
      
 40 
     | 
    
         
            +
                  cache_stats
         
     | 
| 
      
 41 
     | 
    
         
            +
                  @stats[:total][:insertions]
         
     | 
| 
      
 42 
     | 
    
         
            +
                end
         
     | 
| 
      
 43 
     | 
    
         
            +
                
         
     | 
| 
      
 44 
     | 
    
         
            +
                def stats
         
     | 
| 
      
 45 
     | 
    
         
            +
                  cache_stats
         
     | 
| 
      
 46 
     | 
    
         
            +
                  @stats
         
     | 
| 
      
 47 
     | 
    
         
            +
                end
         
     | 
| 
      
 48 
     | 
    
         
            +
                
         
     | 
| 
      
 49 
     | 
    
         
            +
                # if file is provided and is writable, it will write the patch into the file
         
     | 
| 
      
 50 
     | 
    
         
            +
                def patch(file = nil)
         
     | 
| 
      
 51 
     | 
    
         
            +
                  cache_full
         
     | 
| 
      
 52 
     | 
    
         
            +
                  @full_diff
         
     | 
| 
      
 53 
     | 
    
         
            +
                end
         
     | 
| 
      
 54 
     | 
    
         
            +
                alias_method :to_s, :patch
         
     | 
| 
      
 55 
     | 
    
         
            +
                
         
     | 
| 
      
 56 
     | 
    
         
            +
                # enumerable methods
         
     | 
| 
      
 57 
     | 
    
         
            +
                
         
     | 
| 
      
 58 
     | 
    
         
            +
                def [](key)
         
     | 
| 
      
 59 
     | 
    
         
            +
                  process_full
         
     | 
| 
      
 60 
     | 
    
         
            +
                  @full_diff_files.assoc(key)[1]
         
     | 
| 
      
 61 
     | 
    
         
            +
                end
         
     | 
| 
      
 62 
     | 
    
         
            +
                
         
     | 
| 
      
 63 
     | 
    
         
            +
                def each(&block) # :yields: each Git::DiffFile in turn
         
     | 
| 
      
 64 
     | 
    
         
            +
                  process_full
         
     | 
| 
      
 65 
     | 
    
         
            +
                  @full_diff_files.map { |file| file[1] }.each(&block)
         
     | 
| 
      
 66 
     | 
    
         
            +
                end
         
     | 
| 
      
 67 
     | 
    
         
            +
                
         
     | 
| 
      
 68 
     | 
    
         
            +
                class DiffFile
         
     | 
| 
      
 69 
     | 
    
         
            +
                  attr_accessor :patch, :path, :mode, :src, :dst, :type
         
     | 
| 
      
 70 
     | 
    
         
            +
                  @base = nil
         
     | 
| 
      
 71 
     | 
    
         
            +
                  
         
     | 
| 
      
 72 
     | 
    
         
            +
                  def initialize(base, hash)
         
     | 
| 
      
 73 
     | 
    
         
            +
                    @base = base
         
     | 
| 
      
 74 
     | 
    
         
            +
                    @patch = hash[:patch]
         
     | 
| 
      
 75 
     | 
    
         
            +
                    @path = hash[:path]
         
     | 
| 
      
 76 
     | 
    
         
            +
                    @mode = hash[:mode]
         
     | 
| 
      
 77 
     | 
    
         
            +
                    @src = hash[:src]
         
     | 
| 
      
 78 
     | 
    
         
            +
                    @dst = hash[:dst]
         
     | 
| 
      
 79 
     | 
    
         
            +
                    @type = hash[:type]
         
     | 
| 
      
 80 
     | 
    
         
            +
                    @binary = hash[:binary]
         
     | 
| 
      
 81 
     | 
    
         
            +
                  end
         
     | 
| 
      
 82 
     | 
    
         
            +
             
     | 
| 
      
 83 
     | 
    
         
            +
                  def binary?
         
     | 
| 
      
 84 
     | 
    
         
            +
                    !!@binary
         
     | 
| 
      
 85 
     | 
    
         
            +
                  end
         
     | 
| 
      
 86 
     | 
    
         
            +
                  
         
     | 
| 
      
 87 
     | 
    
         
            +
                  def blob(type = :dst)
         
     | 
| 
      
 88 
     | 
    
         
            +
                    if type == :src
         
     | 
| 
      
 89 
     | 
    
         
            +
                      @base.object(@src) if @src != '0000000'
         
     | 
| 
      
 90 
     | 
    
         
            +
                    else
         
     | 
| 
      
 91 
     | 
    
         
            +
                      @base.object(@dst) if @dst != '0000000'
         
     | 
| 
      
 92 
     | 
    
         
            +
                    end
         
     | 
| 
      
 93 
     | 
    
         
            +
                  end
         
     | 
| 
      
 94 
     | 
    
         
            +
                end
         
     | 
| 
      
 95 
     | 
    
         
            +
                
         
     | 
| 
      
 96 
     | 
    
         
            +
                private
         
     | 
| 
      
 97 
     | 
    
         
            +
                
         
     | 
| 
      
 98 
     | 
    
         
            +
                  def cache_full
         
     | 
| 
      
 99 
     | 
    
         
            +
                    unless @full_diff
         
     | 
| 
      
 100 
     | 
    
         
            +
                      @full_diff = @base.lib.diff_full(@from, @to, {:path_limiter => @path})
         
     | 
| 
      
 101 
     | 
    
         
            +
                    end
         
     | 
| 
      
 102 
     | 
    
         
            +
                  end
         
     | 
| 
      
 103 
     | 
    
         
            +
                  
         
     | 
| 
      
 104 
     | 
    
         
            +
                  def process_full
         
     | 
| 
      
 105 
     | 
    
         
            +
                    unless @full_diff_files
         
     | 
| 
      
 106 
     | 
    
         
            +
                      cache_full
         
     | 
| 
      
 107 
     | 
    
         
            +
                      @full_diff_files = process_full_diff
         
     | 
| 
      
 108 
     | 
    
         
            +
                    end
         
     | 
| 
      
 109 
     | 
    
         
            +
                  end
         
     | 
| 
      
 110 
     | 
    
         
            +
                  
         
     | 
| 
      
 111 
     | 
    
         
            +
                  def cache_stats
         
     | 
| 
      
 112 
     | 
    
         
            +
                    unless @stats
         
     | 
| 
      
 113 
     | 
    
         
            +
                      @stats = @base.lib.diff_stats(@from, @to, {:path_limiter => @path})
         
     | 
| 
      
 114 
     | 
    
         
            +
                    end
         
     | 
| 
      
 115 
     | 
    
         
            +
                  end
         
     | 
| 
      
 116 
     | 
    
         
            +
                  
         
     | 
| 
      
 117 
     | 
    
         
            +
                  # break up @diff_full
         
     | 
| 
      
 118 
     | 
    
         
            +
                  def process_full_diff
         
     | 
| 
      
 119 
     | 
    
         
            +
                    final = {}
         
     | 
| 
      
 120 
     | 
    
         
            +
                    current_file = nil
         
     | 
| 
      
 121 
     | 
    
         
            +
                    @full_diff.split("\n").each do |line|
         
     | 
| 
      
 122 
     | 
    
         
            +
                      if m = /diff --git a\/(.*?) b\/(.*?)/.match(line)
         
     | 
| 
      
 123 
     | 
    
         
            +
                        current_file = m[1]
         
     | 
| 
      
 124 
     | 
    
         
            +
                        final[current_file] = {:patch => line, :path => current_file, 
         
     | 
| 
      
 125 
     | 
    
         
            +
                                                :mode => '', :src => '', :dst => '', :type => 'modified'}
         
     | 
| 
      
 126 
     | 
    
         
            +
                      else
         
     | 
| 
      
 127 
     | 
    
         
            +
                        if m = /index (.......)\.\.(.......)( ......)*/.match(line)
         
     | 
| 
      
 128 
     | 
    
         
            +
                          final[current_file][:src] = m[1]
         
     | 
| 
      
 129 
     | 
    
         
            +
                          final[current_file][:dst] = m[2]
         
     | 
| 
      
 130 
     | 
    
         
            +
                          final[current_file][:mode] = m[3].strip if m[3]
         
     | 
| 
      
 131 
     | 
    
         
            +
                        end
         
     | 
| 
      
 132 
     | 
    
         
            +
                        if m = /(.*?) file mode (......)/.match(line)
         
     | 
| 
      
 133 
     | 
    
         
            +
                          final[current_file][:type] = m[1]
         
     | 
| 
      
 134 
     | 
    
         
            +
                          final[current_file][:mode] = m[2]
         
     | 
| 
      
 135 
     | 
    
         
            +
                        end
         
     | 
| 
      
 136 
     | 
    
         
            +
                        if m = /^Binary files /.match(line)
         
     | 
| 
      
 137 
     | 
    
         
            +
                          final[current_file][:binary] = true
         
     | 
| 
      
 138 
     | 
    
         
            +
                        end
         
     | 
| 
      
 139 
     | 
    
         
            +
                        final[current_file][:patch] << "\n" + line 
         
     | 
| 
      
 140 
     | 
    
         
            +
                      end
         
     | 
| 
      
 141 
     | 
    
         
            +
                    end
         
     | 
| 
      
 142 
     | 
    
         
            +
                    final.map { |e| [e[0], DiffFile.new(@base, e[1])] }
         
     | 
| 
      
 143 
     | 
    
         
            +
                  end
         
     | 
| 
      
 144 
     | 
    
         
            +
                  
         
     | 
| 
      
 145 
     | 
    
         
            +
              end
         
     | 
| 
      
 146 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,848 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'tempfile'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module Git
         
     | 
| 
      
 4 
     | 
    
         
            +
              
         
     | 
| 
      
 5 
     | 
    
         
            +
              class GitExecuteError < StandardError 
         
     | 
| 
      
 6 
     | 
    
         
            +
              end
         
     | 
| 
      
 7 
     | 
    
         
            +
              
         
     | 
| 
      
 8 
     | 
    
         
            +
              class Lib
         
     | 
| 
      
 9 
     | 
    
         
            +
                  
         
     | 
| 
      
 10 
     | 
    
         
            +
                def initialize(base = nil, logger = nil)
         
     | 
| 
      
 11 
     | 
    
         
            +
                  @git_dir = nil
         
     | 
| 
      
 12 
     | 
    
         
            +
                  @git_index_file = nil
         
     | 
| 
      
 13 
     | 
    
         
            +
                  @git_work_dir = nil
         
     | 
| 
      
 14 
     | 
    
         
            +
                  @path = nil
         
     | 
| 
      
 15 
     | 
    
         
            +
                  
         
     | 
| 
      
 16 
     | 
    
         
            +
                  if base.is_a?(Git::Base)
         
     | 
| 
      
 17 
     | 
    
         
            +
                    @git_dir = base.repo.path
         
     | 
| 
      
 18 
     | 
    
         
            +
                    @git_index_file = base.index.path if base.index
         
     | 
| 
      
 19 
     | 
    
         
            +
                    @git_work_dir = base.dir.path if base.dir
         
     | 
| 
      
 20 
     | 
    
         
            +
                  elsif base.is_a?(Hash)
         
     | 
| 
      
 21 
     | 
    
         
            +
                    @git_dir = base[:repository]
         
     | 
| 
      
 22 
     | 
    
         
            +
                    @git_index_file = base[:index] 
         
     | 
| 
      
 23 
     | 
    
         
            +
                    @git_work_dir = base[:working_directory]
         
     | 
| 
      
 24 
     | 
    
         
            +
                  end
         
     | 
| 
      
 25 
     | 
    
         
            +
                  @logger = logger
         
     | 
| 
      
 26 
     | 
    
         
            +
                end
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
                # creates or reinitializes the repository
         
     | 
| 
      
 29 
     | 
    
         
            +
                #
         
     | 
| 
      
 30 
     | 
    
         
            +
                # options:
         
     | 
| 
      
 31 
     | 
    
         
            +
                #   :bare
         
     | 
| 
      
 32 
     | 
    
         
            +
                #   :working_directory
         
     | 
| 
      
 33 
     | 
    
         
            +
                #
         
     | 
| 
      
 34 
     | 
    
         
            +
                def init(opts={})
         
     | 
| 
      
 35 
     | 
    
         
            +
                  arr_opts = []
         
     | 
| 
      
 36 
     | 
    
         
            +
                  arr_opts << '--bare' if opts[:bare]
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
                  command('init', arr_opts, false)
         
     | 
| 
      
 39 
     | 
    
         
            +
                end
         
     | 
| 
      
 40 
     | 
    
         
            +
                
         
     | 
| 
      
 41 
     | 
    
         
            +
                # tries to clone the given repo
         
     | 
| 
      
 42 
     | 
    
         
            +
                #
         
     | 
| 
      
 43 
     | 
    
         
            +
                # returns {:repository} (if bare)
         
     | 
| 
      
 44 
     | 
    
         
            +
                #         {:working_directory} otherwise
         
     | 
| 
      
 45 
     | 
    
         
            +
                #
         
     | 
| 
      
 46 
     | 
    
         
            +
                # accepts options:
         
     | 
| 
      
 47 
     | 
    
         
            +
                #  :remote::    name of remote (rather than 'origin')
         
     | 
| 
      
 48 
     | 
    
         
            +
                #  :bare::      no working directory
         
     | 
| 
      
 49 
     | 
    
         
            +
                #  :recursive:: after the clone is created, initialize all submodules within, using their default settings.
         
     | 
| 
      
 50 
     | 
    
         
            +
                #  :depth::     the number of commits back to pull
         
     | 
| 
      
 51 
     | 
    
         
            +
                # 
         
     | 
| 
      
 52 
     | 
    
         
            +
                # TODO - make this work with SSH password or auth_key
         
     | 
| 
      
 53 
     | 
    
         
            +
                #
         
     | 
| 
      
 54 
     | 
    
         
            +
                def clone(repository, name, opts = {})
         
     | 
| 
      
 55 
     | 
    
         
            +
                  @path = opts[:path] || '.'
         
     | 
| 
      
 56 
     | 
    
         
            +
                  clone_dir = opts[:path] ? File.join(@path, name) : name
         
     | 
| 
      
 57 
     | 
    
         
            +
                  
         
     | 
| 
      
 58 
     | 
    
         
            +
                  arr_opts = []
         
     | 
| 
      
 59 
     | 
    
         
            +
                  arr_opts << "--bare" if opts[:bare]
         
     | 
| 
      
 60 
     | 
    
         
            +
                  arr_opts << "--recursive" if opts[:recursive]
         
     | 
| 
      
 61 
     | 
    
         
            +
                  arr_opts << "-o" << opts[:remote] if opts[:remote]
         
     | 
| 
      
 62 
     | 
    
         
            +
                  arr_opts << "--depth" << opts[:depth].to_i if opts[:depth] && opts[:depth].to_i > 0
         
     | 
| 
      
 63 
     | 
    
         
            +
                  arr_opts << "--config" << opts[:config] if opts[:config]
         
     | 
| 
      
 64 
     | 
    
         
            +
             
     | 
| 
      
 65 
     | 
    
         
            +
                  arr_opts << '--'
         
     | 
| 
      
 66 
     | 
    
         
            +
                  arr_opts << repository
         
     | 
| 
      
 67 
     | 
    
         
            +
                  arr_opts << clone_dir
         
     | 
| 
      
 68 
     | 
    
         
            +
                  
         
     | 
| 
      
 69 
     | 
    
         
            +
                  command('clone', arr_opts)
         
     | 
| 
      
 70 
     | 
    
         
            +
                  
         
     | 
| 
      
 71 
     | 
    
         
            +
                  opts[:bare] ? {:repository => clone_dir} : {:working_directory => clone_dir}
         
     | 
| 
      
 72 
     | 
    
         
            +
                end
         
     | 
| 
      
 73 
     | 
    
         
            +
                
         
     | 
| 
      
 74 
     | 
    
         
            +
                
         
     | 
| 
      
 75 
     | 
    
         
            +
                ## READ COMMANDS ##
         
     | 
| 
      
 76 
     | 
    
         
            +
                
         
     | 
| 
      
 77 
     | 
    
         
            +
                def log_commits(opts={})
         
     | 
| 
      
 78 
     | 
    
         
            +
                  arr_opts = log_common_options(opts)
         
     | 
| 
      
 79 
     | 
    
         
            +
                
         
     | 
| 
      
 80 
     | 
    
         
            +
                  arr_opts << '--pretty=oneline'
         
     | 
| 
      
 81 
     | 
    
         
            +
                 
         
     | 
| 
      
 82 
     | 
    
         
            +
                  arr_opts += log_path_options(opts)
         
     | 
| 
      
 83 
     | 
    
         
            +
             
     | 
| 
      
 84 
     | 
    
         
            +
                  command_lines('log', arr_opts, true).map { |l| l.split.first }
         
     | 
| 
      
 85 
     | 
    
         
            +
                end
         
     | 
| 
      
 86 
     | 
    
         
            +
                
         
     | 
| 
      
 87 
     | 
    
         
            +
                def full_log_commits(opts={})
         
     | 
| 
      
 88 
     | 
    
         
            +
                  arr_opts = log_common_options(opts)
         
     | 
| 
      
 89 
     | 
    
         
            +
                
         
     | 
| 
      
 90 
     | 
    
         
            +
                  arr_opts << '--pretty=raw'
         
     | 
| 
      
 91 
     | 
    
         
            +
                  arr_opts << "--skip=#{opts[:skip]}" if opts[:skip]
         
     | 
| 
      
 92 
     | 
    
         
            +
               
         
     | 
| 
      
 93 
     | 
    
         
            +
                  arr_opts += log_path_options(opts)
         
     | 
| 
      
 94 
     | 
    
         
            +
                  
         
     | 
| 
      
 95 
     | 
    
         
            +
                  full_log = command_lines('log', arr_opts, true)
         
     | 
| 
      
 96 
     | 
    
         
            +
             
     | 
| 
      
 97 
     | 
    
         
            +
                  process_commit_log_data(full_log)
         
     | 
| 
      
 98 
     | 
    
         
            +
                end
         
     | 
| 
      
 99 
     | 
    
         
            +
                
         
     | 
| 
      
 100 
     | 
    
         
            +
                def revparse(string)
         
     | 
| 
      
 101 
     | 
    
         
            +
                  return string if string =~ /[A-Fa-f0-9]{40}/  # passing in a sha - just no-op it
         
     | 
| 
      
 102 
     | 
    
         
            +
                  rev = ['head', 'remotes', 'tags'].map do |d|
         
     | 
| 
      
 103 
     | 
    
         
            +
                    File.join(@git_dir, 'refs', d, string)
         
     | 
| 
      
 104 
     | 
    
         
            +
                  end.find do |path|
         
     | 
| 
      
 105 
     | 
    
         
            +
                    File.file?(path)
         
     | 
| 
      
 106 
     | 
    
         
            +
                  end
         
     | 
| 
      
 107 
     | 
    
         
            +
                  return File.read(rev).chomp if rev
         
     | 
| 
      
 108 
     | 
    
         
            +
                  command('rev-parse', string)
         
     | 
| 
      
 109 
     | 
    
         
            +
                end
         
     | 
| 
      
 110 
     | 
    
         
            +
                
         
     | 
| 
      
 111 
     | 
    
         
            +
                def namerev(string)
         
     | 
| 
      
 112 
     | 
    
         
            +
                  command('name-rev', string).split[1]
         
     | 
| 
      
 113 
     | 
    
         
            +
                end
         
     | 
| 
      
 114 
     | 
    
         
            +
                
         
     | 
| 
      
 115 
     | 
    
         
            +
                def object_type(sha)
         
     | 
| 
      
 116 
     | 
    
         
            +
                  command('cat-file', ['-t', sha])
         
     | 
| 
      
 117 
     | 
    
         
            +
                end
         
     | 
| 
      
 118 
     | 
    
         
            +
                
         
     | 
| 
      
 119 
     | 
    
         
            +
                def object_size(sha)
         
     | 
| 
      
 120 
     | 
    
         
            +
                  command('cat-file', ['-s', sha]).to_i
         
     | 
| 
      
 121 
     | 
    
         
            +
                end
         
     | 
| 
      
 122 
     | 
    
         
            +
                
         
     | 
| 
      
 123 
     | 
    
         
            +
                # returns useful array of raw commit object data
         
     | 
| 
      
 124 
     | 
    
         
            +
                def commit_data(sha)
         
     | 
| 
      
 125 
     | 
    
         
            +
                  sha = sha.to_s
         
     | 
| 
      
 126 
     | 
    
         
            +
                  cdata = command_lines('cat-file', ['commit', sha])
         
     | 
| 
      
 127 
     | 
    
         
            +
                  process_commit_data(cdata, sha, 0)
         
     | 
| 
      
 128 
     | 
    
         
            +
                end
         
     | 
| 
      
 129 
     | 
    
         
            +
                
         
     | 
| 
      
 130 
     | 
    
         
            +
                def process_commit_data(data, sha = nil, indent = 4)
         
     | 
| 
      
 131 
     | 
    
         
            +
                  hsh = {
         
     | 
| 
      
 132 
     | 
    
         
            +
                    'sha'     => sha,
         
     | 
| 
      
 133 
     | 
    
         
            +
                    'message' => '',
         
     | 
| 
      
 134 
     | 
    
         
            +
                    'parent'  => []
         
     | 
| 
      
 135 
     | 
    
         
            +
                  }
         
     | 
| 
      
 136 
     | 
    
         
            +
                  
         
     | 
| 
      
 137 
     | 
    
         
            +
                  loop do
         
     | 
| 
      
 138 
     | 
    
         
            +
                    key, *value = data.shift.split
         
     | 
| 
      
 139 
     | 
    
         
            +
             
     | 
| 
      
 140 
     | 
    
         
            +
                    break if key.nil?
         
     | 
| 
      
 141 
     | 
    
         
            +
             
     | 
| 
      
 142 
     | 
    
         
            +
                    if key == 'parent'
         
     | 
| 
      
 143 
     | 
    
         
            +
                      hsh['parent'] << value.join(' ')
         
     | 
| 
      
 144 
     | 
    
         
            +
                    else
         
     | 
| 
      
 145 
     | 
    
         
            +
                      hsh[key] = value.join(' ')
         
     | 
| 
      
 146 
     | 
    
         
            +
                    end
         
     | 
| 
      
 147 
     | 
    
         
            +
                  end
         
     | 
| 
      
 148 
     | 
    
         
            +
                  
         
     | 
| 
      
 149 
     | 
    
         
            +
                  hsh['message'] = data.collect {|line| line[indent..-1]}.join("\n") + "\n"
         
     | 
| 
      
 150 
     | 
    
         
            +
             
     | 
| 
      
 151 
     | 
    
         
            +
                  return hsh
         
     | 
| 
      
 152 
     | 
    
         
            +
                end
         
     | 
| 
      
 153 
     | 
    
         
            +
                
         
     | 
| 
      
 154 
     | 
    
         
            +
                def process_commit_log_data(data)
         
     | 
| 
      
 155 
     | 
    
         
            +
                  in_message = false
         
     | 
| 
      
 156 
     | 
    
         
            +
                        
         
     | 
| 
      
 157 
     | 
    
         
            +
                  hsh_array = []       
         
     | 
| 
      
 158 
     | 
    
         
            +
             
     | 
| 
      
 159 
     | 
    
         
            +
                  hsh = nil
         
     | 
| 
      
 160 
     | 
    
         
            +
                
         
     | 
| 
      
 161 
     | 
    
         
            +
                  data.each do |line|
         
     | 
| 
      
 162 
     | 
    
         
            +
                    line = line.chomp
         
     | 
| 
      
 163 
     | 
    
         
            +
                    
         
     | 
| 
      
 164 
     | 
    
         
            +
                    if line[0].nil?
         
     | 
| 
      
 165 
     | 
    
         
            +
                      in_message = !in_message 
         
     | 
| 
      
 166 
     | 
    
         
            +
                      next
         
     | 
| 
      
 167 
     | 
    
         
            +
                    end
         
     | 
| 
      
 168 
     | 
    
         
            +
                   
         
     | 
| 
      
 169 
     | 
    
         
            +
                    if in_message
         
     | 
| 
      
 170 
     | 
    
         
            +
                      hsh['message'] << "#{line[4..-1]}\n"
         
     | 
| 
      
 171 
     | 
    
         
            +
                      next
         
     | 
| 
      
 172 
     | 
    
         
            +
                    end
         
     | 
| 
      
 173 
     | 
    
         
            +
             
     | 
| 
      
 174 
     | 
    
         
            +
                    key, *value = line.split
         
     | 
| 
      
 175 
     | 
    
         
            +
                    value = value.join(' ')
         
     | 
| 
      
 176 
     | 
    
         
            +
                    
         
     | 
| 
      
 177 
     | 
    
         
            +
                    case key
         
     | 
| 
      
 178 
     | 
    
         
            +
                      when 'commit'
         
     | 
| 
      
 179 
     | 
    
         
            +
                        hsh_array << hsh if hsh
         
     | 
| 
      
 180 
     | 
    
         
            +
                        hsh = {'sha' => value, 'message' => '', 'parent' => []}
         
     | 
| 
      
 181 
     | 
    
         
            +
                      when 'parent'
         
     | 
| 
      
 182 
     | 
    
         
            +
                        hsh['parent'] << value
         
     | 
| 
      
 183 
     | 
    
         
            +
                      else
         
     | 
| 
      
 184 
     | 
    
         
            +
                        hsh[key] = value
         
     | 
| 
      
 185 
     | 
    
         
            +
                    end
         
     | 
| 
      
 186 
     | 
    
         
            +
                  end
         
     | 
| 
      
 187 
     | 
    
         
            +
                  
         
     | 
| 
      
 188 
     | 
    
         
            +
                  hsh_array << hsh if hsh
         
     | 
| 
      
 189 
     | 
    
         
            +
                    
         
     | 
| 
      
 190 
     | 
    
         
            +
                  return hsh_array
         
     | 
| 
      
 191 
     | 
    
         
            +
                end
         
     | 
| 
      
 192 
     | 
    
         
            +
                
         
     | 
| 
      
 193 
     | 
    
         
            +
                def object_contents(sha, &block)
         
     | 
| 
      
 194 
     | 
    
         
            +
                  command('cat-file', ['-p', sha], &block)
         
     | 
| 
      
 195 
     | 
    
         
            +
                end
         
     | 
| 
      
 196 
     | 
    
         
            +
             
     | 
| 
      
 197 
     | 
    
         
            +
                def ls_tree(sha)
         
     | 
| 
      
 198 
     | 
    
         
            +
                  data = {'blob' => {}, 'tree' => {}}
         
     | 
| 
      
 199 
     | 
    
         
            +
                  
         
     | 
| 
      
 200 
     | 
    
         
            +
                  command_lines('ls-tree', sha).each do |line|
         
     | 
| 
      
 201 
     | 
    
         
            +
                    (info, filenm) = line.split("\t")
         
     | 
| 
      
 202 
     | 
    
         
            +
                    (mode, type, sha) = info.split
         
     | 
| 
      
 203 
     | 
    
         
            +
                    data[type][filenm] = {:mode => mode, :sha => sha}
         
     | 
| 
      
 204 
     | 
    
         
            +
                  end
         
     | 
| 
      
 205 
     | 
    
         
            +
                  
         
     | 
| 
      
 206 
     | 
    
         
            +
                  data
         
     | 
| 
      
 207 
     | 
    
         
            +
                end
         
     | 
| 
      
 208 
     | 
    
         
            +
             
     | 
| 
      
 209 
     | 
    
         
            +
                def mv(file1, file2)
         
     | 
| 
      
 210 
     | 
    
         
            +
                  command_lines('mv', ['--', file1, file2])
         
     | 
| 
      
 211 
     | 
    
         
            +
                end
         
     | 
| 
      
 212 
     | 
    
         
            +
                    
         
     | 
| 
      
 213 
     | 
    
         
            +
                def full_tree(sha)
         
     | 
| 
      
 214 
     | 
    
         
            +
                  command_lines('ls-tree', ['-r', sha])
         
     | 
| 
      
 215 
     | 
    
         
            +
                end
         
     | 
| 
      
 216 
     | 
    
         
            +
                        
         
     | 
| 
      
 217 
     | 
    
         
            +
                def tree_depth(sha)
         
     | 
| 
      
 218 
     | 
    
         
            +
                  full_tree(sha).size
         
     | 
| 
      
 219 
     | 
    
         
            +
                end
         
     | 
| 
      
 220 
     | 
    
         
            +
             
     | 
| 
      
 221 
     | 
    
         
            +
                def change_head_branch(branch_name)
         
     | 
| 
      
 222 
     | 
    
         
            +
                  command('symbolic-ref', ['HEAD', "refs/heads/#{branch_name}"])
         
     | 
| 
      
 223 
     | 
    
         
            +
                end
         
     | 
| 
      
 224 
     | 
    
         
            +
                
         
     | 
| 
      
 225 
     | 
    
         
            +
                def branches_all
         
     | 
| 
      
 226 
     | 
    
         
            +
                  arr = []
         
     | 
| 
      
 227 
     | 
    
         
            +
                  command_lines('branch', '-a').each do |b| 
         
     | 
| 
      
 228 
     | 
    
         
            +
                    current = (b[0, 2] == '* ')
         
     | 
| 
      
 229 
     | 
    
         
            +
                    arr << [b.gsub('* ', '').strip, current]
         
     | 
| 
      
 230 
     | 
    
         
            +
                  end
         
     | 
| 
      
 231 
     | 
    
         
            +
                  arr
         
     | 
| 
      
 232 
     | 
    
         
            +
                end
         
     | 
| 
      
 233 
     | 
    
         
            +
             
     | 
| 
      
 234 
     | 
    
         
            +
                def list_files(ref_dir)
         
     | 
| 
      
 235 
     | 
    
         
            +
                  dir = File.join(@git_dir, 'refs', ref_dir)
         
     | 
| 
      
 236 
     | 
    
         
            +
                  files = []
         
     | 
| 
      
 237 
     | 
    
         
            +
                  Dir.chdir(dir) { files = Dir.glob('**/*').select { |f| File.file?(f) } } rescue nil
         
     | 
| 
      
 238 
     | 
    
         
            +
                  files
         
     | 
| 
      
 239 
     | 
    
         
            +
                end
         
     | 
| 
      
 240 
     | 
    
         
            +
                
         
     | 
| 
      
 241 
     | 
    
         
            +
                def branch_current
         
     | 
| 
      
 242 
     | 
    
         
            +
                  branches_all.select { |b| b[1] }.first[0] rescue nil
         
     | 
| 
      
 243 
     | 
    
         
            +
                end
         
     | 
| 
      
 244 
     | 
    
         
            +
             
     | 
| 
      
 245 
     | 
    
         
            +
             
     | 
| 
      
 246 
     | 
    
         
            +
                # returns hash
         
     | 
| 
      
 247 
     | 
    
         
            +
                # [tree-ish] = [[line_no, match], [line_no, match2]]
         
     | 
| 
      
 248 
     | 
    
         
            +
                # [tree-ish] = [[line_no, match], [line_no, match2]]
         
     | 
| 
      
 249 
     | 
    
         
            +
                def grep(string, opts = {})
         
     | 
| 
      
 250 
     | 
    
         
            +
                  opts[:object] ||= 'HEAD'
         
     | 
| 
      
 251 
     | 
    
         
            +
             
     | 
| 
      
 252 
     | 
    
         
            +
                  grep_opts = ['-n']
         
     | 
| 
      
 253 
     | 
    
         
            +
                  grep_opts << '-i' if opts[:ignore_case]
         
     | 
| 
      
 254 
     | 
    
         
            +
                  grep_opts << '-v' if opts[:invert_match]
         
     | 
| 
      
 255 
     | 
    
         
            +
                  grep_opts << '-e'
         
     | 
| 
      
 256 
     | 
    
         
            +
                  grep_opts << string
         
     | 
| 
      
 257 
     | 
    
         
            +
                  grep_opts << opts[:object] if opts[:object].is_a?(String)
         
     | 
| 
      
 258 
     | 
    
         
            +
                  grep_opts << '--' << opts[:path_limiter] if opts[:path_limiter].is_a? String
         
     | 
| 
      
 259 
     | 
    
         
            +
             
     | 
| 
      
 260 
     | 
    
         
            +
                  hsh = {}
         
     | 
| 
      
 261 
     | 
    
         
            +
                  command_lines('grep', grep_opts).each do |line|
         
     | 
| 
      
 262 
     | 
    
         
            +
                    if m = /(.*)\:(\d+)\:(.*)/.match(line)        
         
     | 
| 
      
 263 
     | 
    
         
            +
                      hsh[m[1]] ||= []
         
     | 
| 
      
 264 
     | 
    
         
            +
                      hsh[m[1]] << [m[2].to_i, m[3]] 
         
     | 
| 
      
 265 
     | 
    
         
            +
                    end
         
     | 
| 
      
 266 
     | 
    
         
            +
                  end
         
     | 
| 
      
 267 
     | 
    
         
            +
                  hsh
         
     | 
| 
      
 268 
     | 
    
         
            +
                end
         
     | 
| 
      
 269 
     | 
    
         
            +
                
         
     | 
| 
      
 270 
     | 
    
         
            +
                def diff_full(obj1 = 'HEAD', obj2 = nil, opts = {})
         
     | 
| 
      
 271 
     | 
    
         
            +
                  diff_opts = ['-p']
         
     | 
| 
      
 272 
     | 
    
         
            +
                  diff_opts << obj1
         
     | 
| 
      
 273 
     | 
    
         
            +
                  diff_opts << obj2 if obj2.is_a?(String)
         
     | 
| 
      
 274 
     | 
    
         
            +
                  diff_opts << '--' << opts[:path_limiter] if opts[:path_limiter].is_a? String
         
     | 
| 
      
 275 
     | 
    
         
            +
             
     | 
| 
      
 276 
     | 
    
         
            +
                  command('diff', diff_opts)
         
     | 
| 
      
 277 
     | 
    
         
            +
                end
         
     | 
| 
      
 278 
     | 
    
         
            +
                
         
     | 
| 
      
 279 
     | 
    
         
            +
                def diff_stats(obj1 = 'HEAD', obj2 = nil, opts = {})
         
     | 
| 
      
 280 
     | 
    
         
            +
                  diff_opts = ['--numstat']
         
     | 
| 
      
 281 
     | 
    
         
            +
                  diff_opts << obj1
         
     | 
| 
      
 282 
     | 
    
         
            +
                  diff_opts << obj2 if obj2.is_a?(String)
         
     | 
| 
      
 283 
     | 
    
         
            +
                  diff_opts << '--' << opts[:path_limiter] if opts[:path_limiter].is_a? String
         
     | 
| 
      
 284 
     | 
    
         
            +
             
     | 
| 
      
 285 
     | 
    
         
            +
                  hsh = {:total => {:insertions => 0, :deletions => 0, :lines => 0, :files => 0}, :files => {}}
         
     | 
| 
      
 286 
     | 
    
         
            +
                  
         
     | 
| 
      
 287 
     | 
    
         
            +
                  command_lines('diff', diff_opts).each do |file|
         
     | 
| 
      
 288 
     | 
    
         
            +
                    (insertions, deletions, filename) = file.split("\t")
         
     | 
| 
      
 289 
     | 
    
         
            +
                    hsh[:total][:insertions] += insertions.to_i
         
     | 
| 
      
 290 
     | 
    
         
            +
                    hsh[:total][:deletions] += deletions.to_i
         
     | 
| 
      
 291 
     | 
    
         
            +
                    hsh[:total][:lines] = (hsh[:total][:deletions] + hsh[:total][:insertions])
         
     | 
| 
      
 292 
     | 
    
         
            +
                    hsh[:total][:files] += 1
         
     | 
| 
      
 293 
     | 
    
         
            +
                    hsh[:files][filename] = {:insertions => insertions.to_i, :deletions => deletions.to_i}
         
     | 
| 
      
 294 
     | 
    
         
            +
                  end
         
     | 
| 
      
 295 
     | 
    
         
            +
                        
         
     | 
| 
      
 296 
     | 
    
         
            +
                  hsh
         
     | 
| 
      
 297 
     | 
    
         
            +
                end
         
     | 
| 
      
 298 
     | 
    
         
            +
             
     | 
| 
      
 299 
     | 
    
         
            +
                # compares the index and the working directory
         
     | 
| 
      
 300 
     | 
    
         
            +
                def diff_files
         
     | 
| 
      
 301 
     | 
    
         
            +
                  diff_as_hash('diff-files')
         
     | 
| 
      
 302 
     | 
    
         
            +
                end
         
     | 
| 
      
 303 
     | 
    
         
            +
                
         
     | 
| 
      
 304 
     | 
    
         
            +
                # compares the index and the repository
         
     | 
| 
      
 305 
     | 
    
         
            +
                def diff_index(treeish)
         
     | 
| 
      
 306 
     | 
    
         
            +
                  diff_as_hash('diff-index', treeish)
         
     | 
| 
      
 307 
     | 
    
         
            +
                end
         
     | 
| 
      
 308 
     | 
    
         
            +
                        
         
     | 
| 
      
 309 
     | 
    
         
            +
                def ls_files(location=nil)
         
     | 
| 
      
 310 
     | 
    
         
            +
                  hsh = {}
         
     | 
| 
      
 311 
     | 
    
         
            +
                  command_lines('ls-files', ['--stage', location]).each do |line|
         
     | 
| 
      
 312 
     | 
    
         
            +
                    (info, file) = line.split("\t")
         
     | 
| 
      
 313 
     | 
    
         
            +
                    (mode, sha, stage) = info.split
         
     | 
| 
      
 314 
     | 
    
         
            +
                    file = eval(file) if file =~ /^\".*\"$/ # This takes care of quoted strings returned from git
         
     | 
| 
      
 315 
     | 
    
         
            +
                    hsh[file] = {:path => file, :mode_index => mode, :sha_index => sha, :stage => stage}
         
     | 
| 
      
 316 
     | 
    
         
            +
                  end
         
     | 
| 
      
 317 
     | 
    
         
            +
                  hsh
         
     | 
| 
      
 318 
     | 
    
         
            +
                end
         
     | 
| 
      
 319 
     | 
    
         
            +
             
     | 
| 
      
 320 
     | 
    
         
            +
                def ls_remote(location=nil)
         
     | 
| 
      
 321 
     | 
    
         
            +
                  Hash.new{ |h,k| h[k] = {} }.tap do |hsh|
         
     | 
| 
      
 322 
     | 
    
         
            +
                    command_lines('ls-remote', [location], false).each do |line|
         
     | 
| 
      
 323 
     | 
    
         
            +
                      (sha, info) = line.split("\t")
         
     | 
| 
      
 324 
     | 
    
         
            +
                      (ref, type, name) = info.split('/', 3)
         
     | 
| 
      
 325 
     | 
    
         
            +
                      type ||= 'head'
         
     | 
| 
      
 326 
     | 
    
         
            +
                      type = 'branches' if type == 'heads'
         
     | 
| 
      
 327 
     | 
    
         
            +
                      value = {:ref => ref, :sha => sha}
         
     | 
| 
      
 328 
     | 
    
         
            +
                      hsh[type].update( name.nil? ? value : { name => value })
         
     | 
| 
      
 329 
     | 
    
         
            +
                    end
         
     | 
| 
      
 330 
     | 
    
         
            +
                  end
         
     | 
| 
      
 331 
     | 
    
         
            +
                end
         
     | 
| 
      
 332 
     | 
    
         
            +
             
     | 
| 
      
 333 
     | 
    
         
            +
                def ignored_files
         
     | 
| 
      
 334 
     | 
    
         
            +
                  command_lines('ls-files', ['--others', '-i', '--exclude-standard'])
         
     | 
| 
      
 335 
     | 
    
         
            +
                end
         
     | 
| 
      
 336 
     | 
    
         
            +
             
     | 
| 
      
 337 
     | 
    
         
            +
             
     | 
| 
      
 338 
     | 
    
         
            +
                def config_remote(name)
         
     | 
| 
      
 339 
     | 
    
         
            +
                  hsh = {}
         
     | 
| 
      
 340 
     | 
    
         
            +
                  config_list.each do |key, value|
         
     | 
| 
      
 341 
     | 
    
         
            +
                    if /remote.#{name}/.match(key)
         
     | 
| 
      
 342 
     | 
    
         
            +
                      hsh[key.gsub("remote.#{name}.", '')] = value
         
     | 
| 
      
 343 
     | 
    
         
            +
                    end
         
     | 
| 
      
 344 
     | 
    
         
            +
                  end
         
     | 
| 
      
 345 
     | 
    
         
            +
                  hsh
         
     | 
| 
      
 346 
     | 
    
         
            +
                end
         
     | 
| 
      
 347 
     | 
    
         
            +
             
     | 
| 
      
 348 
     | 
    
         
            +
                def config_get(name)
         
     | 
| 
      
 349 
     | 
    
         
            +
                  do_get = lambda do |path|
         
     | 
| 
      
 350 
     | 
    
         
            +
                    command('config', ['--get', name])
         
     | 
| 
      
 351 
     | 
    
         
            +
                  end
         
     | 
| 
      
 352 
     | 
    
         
            +
             
     | 
| 
      
 353 
     | 
    
         
            +
                  if @git_dir
         
     | 
| 
      
 354 
     | 
    
         
            +
                    Dir.chdir(@git_dir, &do_get)
         
     | 
| 
      
 355 
     | 
    
         
            +
                  else
         
     | 
| 
      
 356 
     | 
    
         
            +
                    build_list.call
         
     | 
| 
      
 357 
     | 
    
         
            +
                  end
         
     | 
| 
      
 358 
     | 
    
         
            +
                end
         
     | 
| 
      
 359 
     | 
    
         
            +
             
     | 
| 
      
 360 
     | 
    
         
            +
                def global_config_get(name)
         
     | 
| 
      
 361 
     | 
    
         
            +
                  command('config', ['--global', '--get', name], false)
         
     | 
| 
      
 362 
     | 
    
         
            +
                end
         
     | 
| 
      
 363 
     | 
    
         
            +
                
         
     | 
| 
      
 364 
     | 
    
         
            +
                def config_list
         
     | 
| 
      
 365 
     | 
    
         
            +
                  build_list = lambda do |path|
         
     | 
| 
      
 366 
     | 
    
         
            +
                    parse_config_list command_lines('config', ['--list'])
         
     | 
| 
      
 367 
     | 
    
         
            +
                  end
         
     | 
| 
      
 368 
     | 
    
         
            +
                  
         
     | 
| 
      
 369 
     | 
    
         
            +
                  if @git_dir
         
     | 
| 
      
 370 
     | 
    
         
            +
                    Dir.chdir(@git_dir, &build_list)
         
     | 
| 
      
 371 
     | 
    
         
            +
                  else
         
     | 
| 
      
 372 
     | 
    
         
            +
                    build_list.call
         
     | 
| 
      
 373 
     | 
    
         
            +
                  end
         
     | 
| 
      
 374 
     | 
    
         
            +
                end
         
     | 
| 
      
 375 
     | 
    
         
            +
             
     | 
| 
      
 376 
     | 
    
         
            +
                def global_config_list
         
     | 
| 
      
 377 
     | 
    
         
            +
                  parse_config_list command_lines('config', ['--global', '--list'], false)
         
     | 
| 
      
 378 
     | 
    
         
            +
                end
         
     | 
| 
      
 379 
     | 
    
         
            +
                
         
     | 
| 
      
 380 
     | 
    
         
            +
                def parse_config_list(lines)
         
     | 
| 
      
 381 
     | 
    
         
            +
                  hsh = {}
         
     | 
| 
      
 382 
     | 
    
         
            +
                  lines.each do |line|
         
     | 
| 
      
 383 
     | 
    
         
            +
                    (key, *values) = line.split('=')
         
     | 
| 
      
 384 
     | 
    
         
            +
                    hsh[key] = values.join('=')
         
     | 
| 
      
 385 
     | 
    
         
            +
                  end
         
     | 
| 
      
 386 
     | 
    
         
            +
                  hsh
         
     | 
| 
      
 387 
     | 
    
         
            +
                end
         
     | 
| 
      
 388 
     | 
    
         
            +
             
     | 
| 
      
 389 
     | 
    
         
            +
                def parse_config(file)
         
     | 
| 
      
 390 
     | 
    
         
            +
                  parse_config_list command_lines('config', ['--list', '--file', file], false)
         
     | 
| 
      
 391 
     | 
    
         
            +
                end
         
     | 
| 
      
 392 
     | 
    
         
            +
                
         
     | 
| 
      
 393 
     | 
    
         
            +
                ## WRITE COMMANDS ##
         
     | 
| 
      
 394 
     | 
    
         
            +
                    
         
     | 
| 
      
 395 
     | 
    
         
            +
                def config_set(name, value)
         
     | 
| 
      
 396 
     | 
    
         
            +
                  command('config', [name, value])
         
     | 
| 
      
 397 
     | 
    
         
            +
                end
         
     | 
| 
      
 398 
     | 
    
         
            +
             
     | 
| 
      
 399 
     | 
    
         
            +
                def global_config_set(name, value)
         
     | 
| 
      
 400 
     | 
    
         
            +
                  command('config', ['--global', name, value], false)
         
     | 
| 
      
 401 
     | 
    
         
            +
                end
         
     | 
| 
      
 402 
     | 
    
         
            +
                     
         
     | 
| 
      
 403 
     | 
    
         
            +
                # updates the repository index using the workig dorectory content
         
     | 
| 
      
 404 
     | 
    
         
            +
                # 
         
     | 
| 
      
 405 
     | 
    
         
            +
                #    lib.add('path/to/file')
         
     | 
| 
      
 406 
     | 
    
         
            +
                #    lib.add(['path/to/file1','path/to/file2'])
         
     | 
| 
      
 407 
     | 
    
         
            +
                #    lib.add(:all => true)
         
     | 
| 
      
 408 
     | 
    
         
            +
                #
         
     | 
| 
      
 409 
     | 
    
         
            +
                # options:
         
     | 
| 
      
 410 
     | 
    
         
            +
                #   :all => true
         
     | 
| 
      
 411 
     | 
    
         
            +
                #   :force => true
         
     | 
| 
      
 412 
     | 
    
         
            +
                #
         
     | 
| 
      
 413 
     | 
    
         
            +
                # @param [String,Array] paths files paths to be added to the repository
         
     | 
| 
      
 414 
     | 
    
         
            +
                # @param [Hash] options
         
     | 
| 
      
 415 
     | 
    
         
            +
                def add(paths='.',options={})
         
     | 
| 
      
 416 
     | 
    
         
            +
                  arr_opts = []
         
     | 
| 
      
 417 
     | 
    
         
            +
                  
         
     | 
| 
      
 418 
     | 
    
         
            +
                  arr_opts << '--all' if options[:all]
         
     | 
| 
      
 419 
     | 
    
         
            +
                  arr_opts << '--force' if options[:force]
         
     | 
| 
      
 420 
     | 
    
         
            +
             
     | 
| 
      
 421 
     | 
    
         
            +
                  arr_opts << '--' 
         
     | 
| 
      
 422 
     | 
    
         
            +
             
     | 
| 
      
 423 
     | 
    
         
            +
                  arr_opts << paths
         
     | 
| 
      
 424 
     | 
    
         
            +
                  
         
     | 
| 
      
 425 
     | 
    
         
            +
                  arr_opts.flatten!
         
     | 
| 
      
 426 
     | 
    
         
            +
             
     | 
| 
      
 427 
     | 
    
         
            +
                  command('add', arr_opts)
         
     | 
| 
      
 428 
     | 
    
         
            +
                end
         
     | 
| 
      
 429 
     | 
    
         
            +
                
         
     | 
| 
      
 430 
     | 
    
         
            +
                def remove(path = '.', opts = {})
         
     | 
| 
      
 431 
     | 
    
         
            +
                  arr_opts = ['-f']  # overrides the up-to-date check by default
         
     | 
| 
      
 432 
     | 
    
         
            +
                  arr_opts << ['-r'] if opts[:recursive]
         
     | 
| 
      
 433 
     | 
    
         
            +
                  arr_opts << '--'
         
     | 
| 
      
 434 
     | 
    
         
            +
                  if path.is_a?(Array)
         
     | 
| 
      
 435 
     | 
    
         
            +
                    arr_opts += path
         
     | 
| 
      
 436 
     | 
    
         
            +
                  else
         
     | 
| 
      
 437 
     | 
    
         
            +
                    arr_opts << path
         
     | 
| 
      
 438 
     | 
    
         
            +
                  end
         
     | 
| 
      
 439 
     | 
    
         
            +
             
     | 
| 
      
 440 
     | 
    
         
            +
                  command('rm', arr_opts)
         
     | 
| 
      
 441 
     | 
    
         
            +
                end
         
     | 
| 
      
 442 
     | 
    
         
            +
             
     | 
| 
      
 443 
     | 
    
         
            +
                def commit(message, opts = {})
         
     | 
| 
      
 444 
     | 
    
         
            +
                  arr_opts = []
         
     | 
| 
      
 445 
     | 
    
         
            +
                  arr_opts << "--message=#{message}" if message
         
     | 
| 
      
 446 
     | 
    
         
            +
                  arr_opts << '--amend' << '--no-edit' if opts[:amend]
         
     | 
| 
      
 447 
     | 
    
         
            +
                  arr_opts << '--all' if opts[:add_all] || opts[:all] 
         
     | 
| 
      
 448 
     | 
    
         
            +
                  arr_opts << '--allow-empty' if opts[:allow_empty]
         
     | 
| 
      
 449 
     | 
    
         
            +
                  arr_opts << "--author=#{opts[:author]}" if opts[:author]
         
     | 
| 
      
 450 
     | 
    
         
            +
                  
         
     | 
| 
      
 451 
     | 
    
         
            +
                  command('commit', arr_opts)
         
     | 
| 
      
 452 
     | 
    
         
            +
                end
         
     | 
| 
      
 453 
     | 
    
         
            +
             
     | 
| 
      
 454 
     | 
    
         
            +
                def reset(commit, opts = {})
         
     | 
| 
      
 455 
     | 
    
         
            +
                  arr_opts = []
         
     | 
| 
      
 456 
     | 
    
         
            +
                  arr_opts << '--hard' if opts[:hard]
         
     | 
| 
      
 457 
     | 
    
         
            +
                  arr_opts << commit if commit
         
     | 
| 
      
 458 
     | 
    
         
            +
                  command('reset', arr_opts)
         
     | 
| 
      
 459 
     | 
    
         
            +
                end
         
     | 
| 
      
 460 
     | 
    
         
            +
             
     | 
| 
      
 461 
     | 
    
         
            +
                def clean(opts = {})
         
     | 
| 
      
 462 
     | 
    
         
            +
                  arr_opts = [] 
         
     | 
| 
      
 463 
     | 
    
         
            +
                  arr_opts << '--force' if opts[:force]
         
     | 
| 
      
 464 
     | 
    
         
            +
                  arr_opts << '-d' if opts[:d]
         
     | 
| 
      
 465 
     | 
    
         
            +
                  arr_opts << '-x' if opts[:x]
         
     | 
| 
      
 466 
     | 
    
         
            +
             
     | 
| 
      
 467 
     | 
    
         
            +
                  command('clean', arr_opts)
         
     | 
| 
      
 468 
     | 
    
         
            +
                end
         
     | 
| 
      
 469 
     | 
    
         
            +
                
         
     | 
| 
      
 470 
     | 
    
         
            +
                def revert(commitish, opts = {})
         
     | 
| 
      
 471 
     | 
    
         
            +
                  # Forcing --no-edit as default since it's not an interactive session.
         
     | 
| 
      
 472 
     | 
    
         
            +
                  opts = {:no_edit => true}.merge(opts)
         
     | 
| 
      
 473 
     | 
    
         
            +
                  
         
     | 
| 
      
 474 
     | 
    
         
            +
                  arr_opts = []
         
     | 
| 
      
 475 
     | 
    
         
            +
                  arr_opts << '--no-edit' if opts[:no_edit] 
         
     | 
| 
      
 476 
     | 
    
         
            +
                  arr_opts << commitish
         
     | 
| 
      
 477 
     | 
    
         
            +
             
     | 
| 
      
 478 
     | 
    
         
            +
                  command('revert', arr_opts)
         
     | 
| 
      
 479 
     | 
    
         
            +
                end
         
     | 
| 
      
 480 
     | 
    
         
            +
             
     | 
| 
      
 481 
     | 
    
         
            +
                def apply(patch_file)
         
     | 
| 
      
 482 
     | 
    
         
            +
                  arr_opts = []
         
     | 
| 
      
 483 
     | 
    
         
            +
                  arr_opts << '--' << patch_file if patch_file
         
     | 
| 
      
 484 
     | 
    
         
            +
                  command('apply', arr_opts)
         
     | 
| 
      
 485 
     | 
    
         
            +
                end
         
     | 
| 
      
 486 
     | 
    
         
            +
                
         
     | 
| 
      
 487 
     | 
    
         
            +
                def apply_mail(patch_file)
         
     | 
| 
      
 488 
     | 
    
         
            +
                  arr_opts = []
         
     | 
| 
      
 489 
     | 
    
         
            +
                  arr_opts << '--' << patch_file if patch_file
         
     | 
| 
      
 490 
     | 
    
         
            +
                  command('am', arr_opts)
         
     | 
| 
      
 491 
     | 
    
         
            +
                end
         
     | 
| 
      
 492 
     | 
    
         
            +
                
         
     | 
| 
      
 493 
     | 
    
         
            +
                def stashes_all
         
     | 
| 
      
 494 
     | 
    
         
            +
                  arr = []
         
     | 
| 
      
 495 
     | 
    
         
            +
                  filename = File.join(@git_dir, 'logs/refs/stash')
         
     | 
| 
      
 496 
     | 
    
         
            +
                  if File.exist?(filename)
         
     | 
| 
      
 497 
     | 
    
         
            +
                    File.open(filename).each_with_index { |line, i|
         
     | 
| 
      
 498 
     | 
    
         
            +
                      m = line.match(/:(.*)$/)
         
     | 
| 
      
 499 
     | 
    
         
            +
                      arr << [i, m[1].strip]
         
     | 
| 
      
 500 
     | 
    
         
            +
                    }
         
     | 
| 
      
 501 
     | 
    
         
            +
                  end
         
     | 
| 
      
 502 
     | 
    
         
            +
                  arr
         
     | 
| 
      
 503 
     | 
    
         
            +
                end
         
     | 
| 
      
 504 
     | 
    
         
            +
                
         
     | 
| 
      
 505 
     | 
    
         
            +
                def stash_save(message)
         
     | 
| 
      
 506 
     | 
    
         
            +
                  output = command('stash save', ['--', message])
         
     | 
| 
      
 507 
     | 
    
         
            +
                  output =~ /HEAD is now at/
         
     | 
| 
      
 508 
     | 
    
         
            +
                end
         
     | 
| 
      
 509 
     | 
    
         
            +
             
     | 
| 
      
 510 
     | 
    
         
            +
                def stash_apply(id = nil)
         
     | 
| 
      
 511 
     | 
    
         
            +
                  if id
         
     | 
| 
      
 512 
     | 
    
         
            +
                    command('stash apply', [id])
         
     | 
| 
      
 513 
     | 
    
         
            +
                  else
         
     | 
| 
      
 514 
     | 
    
         
            +
                    command('stash apply')
         
     | 
| 
      
 515 
     | 
    
         
            +
                  end
         
     | 
| 
      
 516 
     | 
    
         
            +
                end
         
     | 
| 
      
 517 
     | 
    
         
            +
                
         
     | 
| 
      
 518 
     | 
    
         
            +
                def stash_clear
         
     | 
| 
      
 519 
     | 
    
         
            +
                  command('stash clear')
         
     | 
| 
      
 520 
     | 
    
         
            +
                end
         
     | 
| 
      
 521 
     | 
    
         
            +
                
         
     | 
| 
      
 522 
     | 
    
         
            +
                def stash_list
         
     | 
| 
      
 523 
     | 
    
         
            +
                  command('stash list')
         
     | 
| 
      
 524 
     | 
    
         
            +
                end
         
     | 
| 
      
 525 
     | 
    
         
            +
                
         
     | 
| 
      
 526 
     | 
    
         
            +
                def branch_new(branch)
         
     | 
| 
      
 527 
     | 
    
         
            +
                  command('branch', branch)
         
     | 
| 
      
 528 
     | 
    
         
            +
                end
         
     | 
| 
      
 529 
     | 
    
         
            +
                
         
     | 
| 
      
 530 
     | 
    
         
            +
                def branch_delete(branch)
         
     | 
| 
      
 531 
     | 
    
         
            +
                  command('branch', ['-D', branch])
         
     | 
| 
      
 532 
     | 
    
         
            +
                end
         
     | 
| 
      
 533 
     | 
    
         
            +
                
         
     | 
| 
      
 534 
     | 
    
         
            +
                def checkout(branch, opts = {})
         
     | 
| 
      
 535 
     | 
    
         
            +
                  arr_opts = []
         
     | 
| 
      
 536 
     | 
    
         
            +
                  arr_opts << '-f' if opts[:force]
         
     | 
| 
      
 537 
     | 
    
         
            +
                  arr_opts << '-b' << opts[:new_branch] if opts[:new_branch]
         
     | 
| 
      
 538 
     | 
    
         
            +
                  arr_opts << branch
         
     | 
| 
      
 539 
     | 
    
         
            +
                  
         
     | 
| 
      
 540 
     | 
    
         
            +
                  command('checkout', arr_opts)
         
     | 
| 
      
 541 
     | 
    
         
            +
                end
         
     | 
| 
      
 542 
     | 
    
         
            +
             
     | 
| 
      
 543 
     | 
    
         
            +
                def checkout_file(version, file)
         
     | 
| 
      
 544 
     | 
    
         
            +
                  arr_opts = []
         
     | 
| 
      
 545 
     | 
    
         
            +
                  arr_opts << version
         
     | 
| 
      
 546 
     | 
    
         
            +
                  arr_opts << file
         
     | 
| 
      
 547 
     | 
    
         
            +
                  command('checkout', arr_opts)
         
     | 
| 
      
 548 
     | 
    
         
            +
                end
         
     | 
| 
      
 549 
     | 
    
         
            +
                
         
     | 
| 
      
 550 
     | 
    
         
            +
                def merge(branch, message = nil)      
         
     | 
| 
      
 551 
     | 
    
         
            +
                  arr_opts = []
         
     | 
| 
      
 552 
     | 
    
         
            +
                  arr_opts << '-m' << message if message
         
     | 
| 
      
 553 
     | 
    
         
            +
                  arr_opts += [branch]
         
     | 
| 
      
 554 
     | 
    
         
            +
                  command('merge', arr_opts)
         
     | 
| 
      
 555 
     | 
    
         
            +
                end
         
     | 
| 
      
 556 
     | 
    
         
            +
             
     | 
| 
      
 557 
     | 
    
         
            +
                def unmerged
         
     | 
| 
      
 558 
     | 
    
         
            +
                  unmerged = []
         
     | 
| 
      
 559 
     | 
    
         
            +
                  command_lines('diff', ["--cached"]).each do |line|
         
     | 
| 
      
 560 
     | 
    
         
            +
                    unmerged << $1 if line =~ /^\* Unmerged path (.*)/
         
     | 
| 
      
 561 
     | 
    
         
            +
                  end
         
     | 
| 
      
 562 
     | 
    
         
            +
                  unmerged
         
     | 
| 
      
 563 
     | 
    
         
            +
                end
         
     | 
| 
      
 564 
     | 
    
         
            +
             
     | 
| 
      
 565 
     | 
    
         
            +
                def conflicts # :yields: file, your, their
         
     | 
| 
      
 566 
     | 
    
         
            +
                  self.unmerged.each do |f|
         
     | 
| 
      
 567 
     | 
    
         
            +
                    your = Tempfile.new("YOUR-#{File.basename(f)}").path
         
     | 
| 
      
 568 
     | 
    
         
            +
                    command('show', ":2:#{f}", true, "> #{escape your}") 
         
     | 
| 
      
 569 
     | 
    
         
            +
             
     | 
| 
      
 570 
     | 
    
         
            +
                    their = Tempfile.new("THEIR-#{File.basename(f)}").path
         
     | 
| 
      
 571 
     | 
    
         
            +
                    command('show', ":3:#{f}", true, "> #{escape their}") 
         
     | 
| 
      
 572 
     | 
    
         
            +
                    yield(f, your, their)
         
     | 
| 
      
 573 
     | 
    
         
            +
                  end
         
     | 
| 
      
 574 
     | 
    
         
            +
                end
         
     | 
| 
      
 575 
     | 
    
         
            +
             
     | 
| 
      
 576 
     | 
    
         
            +
                def remote_add(name, url, opts = {})
         
     | 
| 
      
 577 
     | 
    
         
            +
                  arr_opts = ['add']
         
     | 
| 
      
 578 
     | 
    
         
            +
                  arr_opts << '-f' if opts[:with_fetch] || opts[:fetch]
         
     | 
| 
      
 579 
     | 
    
         
            +
                  arr_opts << '-t' << opts[:track] if opts[:track]
         
     | 
| 
      
 580 
     | 
    
         
            +
                  arr_opts << '--'
         
     | 
| 
      
 581 
     | 
    
         
            +
                  arr_opts << name
         
     | 
| 
      
 582 
     | 
    
         
            +
                  arr_opts << url
         
     | 
| 
      
 583 
     | 
    
         
            +
                  
         
     | 
| 
      
 584 
     | 
    
         
            +
                  command('remote', arr_opts)
         
     | 
| 
      
 585 
     | 
    
         
            +
                end
         
     | 
| 
      
 586 
     | 
    
         
            +
                
         
     | 
| 
      
 587 
     | 
    
         
            +
                def remote_remove(name)
         
     | 
| 
      
 588 
     | 
    
         
            +
                  command('remote', ['rm', name])
         
     | 
| 
      
 589 
     | 
    
         
            +
                end
         
     | 
| 
      
 590 
     | 
    
         
            +
                
         
     | 
| 
      
 591 
     | 
    
         
            +
                def remotes
         
     | 
| 
      
 592 
     | 
    
         
            +
                  command_lines('remote')
         
     | 
| 
      
 593 
     | 
    
         
            +
                end
         
     | 
| 
      
 594 
     | 
    
         
            +
             
     | 
| 
      
 595 
     | 
    
         
            +
                def tags
         
     | 
| 
      
 596 
     | 
    
         
            +
                  command_lines('tag')
         
     | 
| 
      
 597 
     | 
    
         
            +
                end
         
     | 
| 
      
 598 
     | 
    
         
            +
             
     | 
| 
      
 599 
     | 
    
         
            +
                def tag(name, *opts)
         
     | 
| 
      
 600 
     | 
    
         
            +
                  target = opts[0].instance_of?(String) ? opts[0] : nil
         
     | 
| 
      
 601 
     | 
    
         
            +
                  
         
     | 
| 
      
 602 
     | 
    
         
            +
                  opts = opts.last.instance_of?(Hash) ? opts.last : {}
         
     | 
| 
      
 603 
     | 
    
         
            +
             
     | 
| 
      
 604 
     | 
    
         
            +
                  if (opts[:a] || opts[:annotate]) && !(opts[:m] || opts[:message])
         
     | 
| 
      
 605 
     | 
    
         
            +
                    raise  "Can not create an [:a|:annotate] tag without the precense of [:m|:message]."
         
     | 
| 
      
 606 
     | 
    
         
            +
                  end
         
     | 
| 
      
 607 
     | 
    
         
            +
             
     | 
| 
      
 608 
     | 
    
         
            +
                  arr_opts = []
         
     | 
| 
      
 609 
     | 
    
         
            +
             
     | 
| 
      
 610 
     | 
    
         
            +
                  arr_opts << '-f' if opts[:force] || opts[:f]
         
     | 
| 
      
 611 
     | 
    
         
            +
                  arr_opts << '-a' if opts[:a] || opts[:annotate]
         
     | 
| 
      
 612 
     | 
    
         
            +
                  arr_opts << '-s' if opts[:s] || opts[:sign]
         
     | 
| 
      
 613 
     | 
    
         
            +
                  arr_opts << '-d' if opts[:d] || opts[:delete]
         
     | 
| 
      
 614 
     | 
    
         
            +
                  arr_opts << name
         
     | 
| 
      
 615 
     | 
    
         
            +
                  arr_opts << target if target
         
     | 
| 
      
 616 
     | 
    
         
            +
                  arr_opts << "-m #{opts[:m] || opts[:message]}" if opts[:m] || opts[:message]
         
     | 
| 
      
 617 
     | 
    
         
            +
                  
         
     | 
| 
      
 618 
     | 
    
         
            +
                  command('tag', arr_opts)
         
     | 
| 
      
 619 
     | 
    
         
            +
                end
         
     | 
| 
      
 620 
     | 
    
         
            +
             
     | 
| 
      
 621 
     | 
    
         
            +
                
         
     | 
| 
      
 622 
     | 
    
         
            +
                def fetch(remote, opts)
         
     | 
| 
      
 623 
     | 
    
         
            +
                  arr_opts = [remote]
         
     | 
| 
      
 624 
     | 
    
         
            +
                  arr_opts << '--tags' if opts[:t] || opts[:tags]
         
     | 
| 
      
 625 
     | 
    
         
            +
             
     | 
| 
      
 626 
     | 
    
         
            +
                  command('fetch', arr_opts)
         
     | 
| 
      
 627 
     | 
    
         
            +
                end
         
     | 
| 
      
 628 
     | 
    
         
            +
                
         
     | 
| 
      
 629 
     | 
    
         
            +
                def push(remote, branch = 'master', opts = {})
         
     | 
| 
      
 630 
     | 
    
         
            +
                  # Small hack to keep backwards compatibility with the 'push(remote, branch, tags)' method signature.
         
     | 
| 
      
 631 
     | 
    
         
            +
                  opts = {:tags => opts} if [true, false].include?(opts) 
         
     | 
| 
      
 632 
     | 
    
         
            +
                  
         
     | 
| 
      
 633 
     | 
    
         
            +
                  arr_opts = []
         
     | 
| 
      
 634 
     | 
    
         
            +
                  arr_opts << '--force'  if opts[:force] || opts[:f]
         
     | 
| 
      
 635 
     | 
    
         
            +
                  arr_opts << remote
         
     | 
| 
      
 636 
     | 
    
         
            +
             
     | 
| 
      
 637 
     | 
    
         
            +
                  command('push', arr_opts + [branch])
         
     | 
| 
      
 638 
     | 
    
         
            +
                  command('push', ['--tags'] + arr_opts) if opts[:tags]
         
     | 
| 
      
 639 
     | 
    
         
            +
                end
         
     | 
| 
      
 640 
     | 
    
         
            +
             
     | 
| 
      
 641 
     | 
    
         
            +
                def pull(remote='origin', branch='master')
         
     | 
| 
      
 642 
     | 
    
         
            +
                  command('pull', [remote, branch])
         
     | 
| 
      
 643 
     | 
    
         
            +
                end
         
     | 
| 
      
 644 
     | 
    
         
            +
             
     | 
| 
      
 645 
     | 
    
         
            +
                def tag_sha(tag_name)
         
     | 
| 
      
 646 
     | 
    
         
            +
                  head = File.join(@git_dir, 'refs', 'tags', tag_name)
         
     | 
| 
      
 647 
     | 
    
         
            +
                  return File.read(head).chomp if File.exists?(head)
         
     | 
| 
      
 648 
     | 
    
         
            +
                  
         
     | 
| 
      
 649 
     | 
    
         
            +
                  command('show-ref',  ['--tags', '-s', tag_name])
         
     | 
| 
      
 650 
     | 
    
         
            +
                end  
         
     | 
| 
      
 651 
     | 
    
         
            +
                
         
     | 
| 
      
 652 
     | 
    
         
            +
                def repack
         
     | 
| 
      
 653 
     | 
    
         
            +
                  command('repack', ['-a', '-d'])
         
     | 
| 
      
 654 
     | 
    
         
            +
                end
         
     | 
| 
      
 655 
     | 
    
         
            +
                
         
     | 
| 
      
 656 
     | 
    
         
            +
                def gc
         
     | 
| 
      
 657 
     | 
    
         
            +
                  command('gc', ['--prune', '--aggressive', '--auto'])
         
     | 
| 
      
 658 
     | 
    
         
            +
                end
         
     | 
| 
      
 659 
     | 
    
         
            +
                
         
     | 
| 
      
 660 
     | 
    
         
            +
                # reads a tree into the current index file
         
     | 
| 
      
 661 
     | 
    
         
            +
                def read_tree(treeish, opts = {})
         
     | 
| 
      
 662 
     | 
    
         
            +
                  arr_opts = []
         
     | 
| 
      
 663 
     | 
    
         
            +
                  arr_opts << "--prefix=#{opts[:prefix]}" if opts[:prefix]
         
     | 
| 
      
 664 
     | 
    
         
            +
                  arr_opts += [treeish]
         
     | 
| 
      
 665 
     | 
    
         
            +
                  command('read-tree', arr_opts)
         
     | 
| 
      
 666 
     | 
    
         
            +
                end
         
     | 
| 
      
 667 
     | 
    
         
            +
                
         
     | 
| 
      
 668 
     | 
    
         
            +
                def write_tree
         
     | 
| 
      
 669 
     | 
    
         
            +
                  command('write-tree')
         
     | 
| 
      
 670 
     | 
    
         
            +
                end
         
     | 
| 
      
 671 
     | 
    
         
            +
                
         
     | 
| 
      
 672 
     | 
    
         
            +
                def commit_tree(tree, opts = {})
         
     | 
| 
      
 673 
     | 
    
         
            +
                  opts[:message] ||= "commit tree #{tree}"
         
     | 
| 
      
 674 
     | 
    
         
            +
                  t = Tempfile.new('commit-message')
         
     | 
| 
      
 675 
     | 
    
         
            +
                  t.write(opts[:message])
         
     | 
| 
      
 676 
     | 
    
         
            +
                  t.close
         
     | 
| 
      
 677 
     | 
    
         
            +
                  
         
     | 
| 
      
 678 
     | 
    
         
            +
                  arr_opts = []
         
     | 
| 
      
 679 
     | 
    
         
            +
                  arr_opts << tree
         
     | 
| 
      
 680 
     | 
    
         
            +
                  arr_opts << '-p' << opts[:parent] if opts[:parent]
         
     | 
| 
      
 681 
     | 
    
         
            +
                  arr_opts += [opts[:parents]].map { |p| ['-p', p] }.flatten if opts[:parents]
         
     | 
| 
      
 682 
     | 
    
         
            +
                  command('commit-tree', arr_opts, true, "< #{escape t.path}")
         
     | 
| 
      
 683 
     | 
    
         
            +
                end
         
     | 
| 
      
 684 
     | 
    
         
            +
                
         
     | 
| 
      
 685 
     | 
    
         
            +
                def update_ref(branch, commit)
         
     | 
| 
      
 686 
     | 
    
         
            +
                  command('update-ref', [branch, commit])
         
     | 
| 
      
 687 
     | 
    
         
            +
                end
         
     | 
| 
      
 688 
     | 
    
         
            +
                
         
     | 
| 
      
 689 
     | 
    
         
            +
                def checkout_index(opts = {})
         
     | 
| 
      
 690 
     | 
    
         
            +
                  arr_opts = []
         
     | 
| 
      
 691 
     | 
    
         
            +
                  arr_opts << "--prefix=#{opts[:prefix]}" if opts[:prefix]
         
     | 
| 
      
 692 
     | 
    
         
            +
                  arr_opts << "--force" if opts[:force]
         
     | 
| 
      
 693 
     | 
    
         
            +
                  arr_opts << "--all" if opts[:all]
         
     | 
| 
      
 694 
     | 
    
         
            +
                  arr_opts << '--' << opts[:path_limiter] if opts[:path_limiter].is_a? String
         
     | 
| 
      
 695 
     | 
    
         
            +
             
     | 
| 
      
 696 
     | 
    
         
            +
                  command('checkout-index', arr_opts)
         
     | 
| 
      
 697 
     | 
    
         
            +
                end
         
     | 
| 
      
 698 
     | 
    
         
            +
                
         
     | 
| 
      
 699 
     | 
    
         
            +
                # creates an archive file
         
     | 
| 
      
 700 
     | 
    
         
            +
                #
         
     | 
| 
      
 701 
     | 
    
         
            +
                # options
         
     | 
| 
      
 702 
     | 
    
         
            +
                #  :format  (zip, tar)
         
     | 
| 
      
 703 
     | 
    
         
            +
                #  :prefix
         
     | 
| 
      
 704 
     | 
    
         
            +
                #  :remote
         
     | 
| 
      
 705 
     | 
    
         
            +
                #  :path
         
     | 
| 
      
 706 
     | 
    
         
            +
                def archive(sha, file = nil, opts = {})
         
     | 
| 
      
 707 
     | 
    
         
            +
                  opts[:format] ||= 'zip'
         
     | 
| 
      
 708 
     | 
    
         
            +
                  
         
     | 
| 
      
 709 
     | 
    
         
            +
                  if opts[:format] == 'tgz'
         
     | 
| 
      
 710 
     | 
    
         
            +
                    opts[:format] = 'tar' 
         
     | 
| 
      
 711 
     | 
    
         
            +
                    opts[:add_gzip] = true
         
     | 
| 
      
 712 
     | 
    
         
            +
                  end
         
     | 
| 
      
 713 
     | 
    
         
            +
                  
         
     | 
| 
      
 714 
     | 
    
         
            +
                  file ||= Tempfile.new('archive').path
         
     | 
| 
      
 715 
     | 
    
         
            +
                  
         
     | 
| 
      
 716 
     | 
    
         
            +
                  arr_opts = []
         
     | 
| 
      
 717 
     | 
    
         
            +
                  arr_opts << "--format=#{opts[:format]}" if opts[:format]
         
     | 
| 
      
 718 
     | 
    
         
            +
                  arr_opts << "--prefix=#{opts[:prefix]}" if opts[:prefix]
         
     | 
| 
      
 719 
     | 
    
         
            +
                  arr_opts << "--remote=#{opts[:remote]}" if opts[:remote]
         
     | 
| 
      
 720 
     | 
    
         
            +
                  arr_opts << sha
         
     | 
| 
      
 721 
     | 
    
         
            +
                  arr_opts << '--' << opts[:path] if opts[:path]
         
     | 
| 
      
 722 
     | 
    
         
            +
                  command('archive', arr_opts, true, (opts[:add_gzip] ? '| gzip' : '') + " > #{escape file}")
         
     | 
| 
      
 723 
     | 
    
         
            +
                  return file
         
     | 
| 
      
 724 
     | 
    
         
            +
                end
         
     | 
| 
      
 725 
     | 
    
         
            +
             
     | 
| 
      
 726 
     | 
    
         
            +
                # returns the current version of git, as an Array of Fixnums.
         
     | 
| 
      
 727 
     | 
    
         
            +
                def current_command_version
         
     | 
| 
      
 728 
     | 
    
         
            +
                  output = command('version', [], false)
         
     | 
| 
      
 729 
     | 
    
         
            +
                  version = output[/\d+\.\d+(\.\d+)+/]
         
     | 
| 
      
 730 
     | 
    
         
            +
                  version.split('.').collect {|i| i.to_i}
         
     | 
| 
      
 731 
     | 
    
         
            +
                end
         
     | 
| 
      
 732 
     | 
    
         
            +
             
     | 
| 
      
 733 
     | 
    
         
            +
                def required_command_version
         
     | 
| 
      
 734 
     | 
    
         
            +
                  [1, 6]
         
     | 
| 
      
 735 
     | 
    
         
            +
                end
         
     | 
| 
      
 736 
     | 
    
         
            +
             
     | 
| 
      
 737 
     | 
    
         
            +
                def meets_required_version?
         
     | 
| 
      
 738 
     | 
    
         
            +
                  (self.current_command_version <=>  self.required_command_version) >= 0
         
     | 
| 
      
 739 
     | 
    
         
            +
                end
         
     | 
| 
      
 740 
     | 
    
         
            +
             
     | 
| 
      
 741 
     | 
    
         
            +
             
     | 
| 
      
 742 
     | 
    
         
            +
                private
         
     | 
| 
      
 743 
     | 
    
         
            +
                
         
     | 
| 
      
 744 
     | 
    
         
            +
                def command_lines(cmd, opts = [], chdir = true, redirect = '')
         
     | 
| 
      
 745 
     | 
    
         
            +
                  command(cmd, opts, chdir).split("\n")
         
     | 
| 
      
 746 
     | 
    
         
            +
                end
         
     | 
| 
      
 747 
     | 
    
         
            +
                
         
     | 
| 
      
 748 
     | 
    
         
            +
                def command(cmd, opts = [], chdir = true, redirect = '', &block)
         
     | 
| 
      
 749 
     | 
    
         
            +
                  ENV['GIT_DIR'] = @git_dir
         
     | 
| 
      
 750 
     | 
    
         
            +
                  ENV['GIT_WORK_TREE'] = @git_work_dir
         
     | 
| 
      
 751 
     | 
    
         
            +
                  ENV['GIT_INDEX_FILE'] = @git_index_file
         
     | 
| 
      
 752 
     | 
    
         
            +
             
     | 
| 
      
 753 
     | 
    
         
            +
                  path = @git_work_dir || @git_dir || @path
         
     | 
| 
      
 754 
     | 
    
         
            +
             
     | 
| 
      
 755 
     | 
    
         
            +
                  opts = [opts].flatten.map {|s| escape(s) }.join(' ')
         
     | 
| 
      
 756 
     | 
    
         
            +
             
     | 
| 
      
 757 
     | 
    
         
            +
                  git_cmd = "git #{cmd} #{opts} #{redirect} 2>&1"
         
     | 
| 
      
 758 
     | 
    
         
            +
             
     | 
| 
      
 759 
     | 
    
         
            +
                  out = nil
         
     | 
| 
      
 760 
     | 
    
         
            +
                  if chdir && (Dir.getwd != path)
         
     | 
| 
      
 761 
     | 
    
         
            +
                    Dir.chdir(path) { out = run_command(git_cmd, &block) } 
         
     | 
| 
      
 762 
     | 
    
         
            +
                  else
         
     | 
| 
      
 763 
     | 
    
         
            +
             
     | 
| 
      
 764 
     | 
    
         
            +
                    out = run_command(git_cmd, &block)
         
     | 
| 
      
 765 
     | 
    
         
            +
                  end
         
     | 
| 
      
 766 
     | 
    
         
            +
                  
         
     | 
| 
      
 767 
     | 
    
         
            +
                  if @logger
         
     | 
| 
      
 768 
     | 
    
         
            +
                    @logger.info(git_cmd)
         
     | 
| 
      
 769 
     | 
    
         
            +
                    @logger.debug(out)
         
     | 
| 
      
 770 
     | 
    
         
            +
                  end
         
     | 
| 
      
 771 
     | 
    
         
            +
                        
         
     | 
| 
      
 772 
     | 
    
         
            +
                  if $?.exitstatus > 0
         
     | 
| 
      
 773 
     | 
    
         
            +
                    if $?.exitstatus == 1 && out == ''
         
     | 
| 
      
 774 
     | 
    
         
            +
                      return ''
         
     | 
| 
      
 775 
     | 
    
         
            +
                    end
         
     | 
| 
      
 776 
     | 
    
         
            +
                    raise Git::GitExecuteError.new(git_cmd + ':' + out.to_s) 
         
     | 
| 
      
 777 
     | 
    
         
            +
                  end
         
     | 
| 
      
 778 
     | 
    
         
            +
                  out
         
     | 
| 
      
 779 
     | 
    
         
            +
                end
         
     | 
| 
      
 780 
     | 
    
         
            +
             
     | 
| 
      
 781 
     | 
    
         
            +
                # Takes the diff command line output (as Array) and parse it into a Hash
         
     | 
| 
      
 782 
     | 
    
         
            +
                #
         
     | 
| 
      
 783 
     | 
    
         
            +
                # @param [String] diff_command the diff commadn to be used
         
     | 
| 
      
 784 
     | 
    
         
            +
                # @param [Array] opts the diff options to be used
         
     | 
| 
      
 785 
     | 
    
         
            +
                # @return [Hash] the diff as Hash
         
     | 
| 
      
 786 
     | 
    
         
            +
                def diff_as_hash(diff_command, opts=[])
         
     | 
| 
      
 787 
     | 
    
         
            +
                  command_lines(diff_command, opts).inject({}) do |memo, line|
         
     | 
| 
      
 788 
     | 
    
         
            +
                    info, file = line.split("\t")
         
     | 
| 
      
 789 
     | 
    
         
            +
                    mode_src, mode_dest, sha_src, sha_dest, type = info.split
         
     | 
| 
      
 790 
     | 
    
         
            +
                    
         
     | 
| 
      
 791 
     | 
    
         
            +
                    memo[file] = {
         
     | 
| 
      
 792 
     | 
    
         
            +
                      :mode_index => mode_dest, 
         
     | 
| 
      
 793 
     | 
    
         
            +
                      :mode_repo => mode_src.to_s[1, 7], 
         
     | 
| 
      
 794 
     | 
    
         
            +
                      :path => file, 
         
     | 
| 
      
 795 
     | 
    
         
            +
                      :sha_repo => sha_src, 
         
     | 
| 
      
 796 
     | 
    
         
            +
                      :sha_index => sha_dest, 
         
     | 
| 
      
 797 
     | 
    
         
            +
                      :type => type
         
     | 
| 
      
 798 
     | 
    
         
            +
                    }
         
     | 
| 
      
 799 
     | 
    
         
            +
             
     | 
| 
      
 800 
     | 
    
         
            +
                    memo
         
     | 
| 
      
 801 
     | 
    
         
            +
                  end
         
     | 
| 
      
 802 
     | 
    
         
            +
                end
         
     | 
| 
      
 803 
     | 
    
         
            +
                
         
     | 
| 
      
 804 
     | 
    
         
            +
                # Returns an array holding the common options for the log commands 
         
     | 
| 
      
 805 
     | 
    
         
            +
                #
         
     | 
| 
      
 806 
     | 
    
         
            +
                # @param [Hash] opts the given options
         
     | 
| 
      
 807 
     | 
    
         
            +
                # @return [Array] the set of common options that the log command will use
         
     | 
| 
      
 808 
     | 
    
         
            +
                def log_common_options(opts)
         
     | 
| 
      
 809 
     | 
    
         
            +
                  arr_opts = []
         
     | 
| 
      
 810 
     | 
    
         
            +
             
     | 
| 
      
 811 
     | 
    
         
            +
                  arr_opts << "-#{opts[:count]}" if opts[:count]
         
     | 
| 
      
 812 
     | 
    
         
            +
                  arr_opts << "--no-color"
         
     | 
| 
      
 813 
     | 
    
         
            +
                  arr_opts << "--since=#{opts[:since]}" if opts[:since].is_a? String
         
     | 
| 
      
 814 
     | 
    
         
            +
                  arr_opts << "--until=#{opts[:until]}" if opts[:until].is_a? String
         
     | 
| 
      
 815 
     | 
    
         
            +
                  arr_opts << "--grep=#{opts[:grep]}" if opts[:grep].is_a? String
         
     | 
| 
      
 816 
     | 
    
         
            +
                  arr_opts << "--author=#{opts[:author]}" if opts[:author].is_a? String
         
     | 
| 
      
 817 
     | 
    
         
            +
                  arr_opts << "#{opts[:between][0].to_s}..#{opts[:between][1].to_s}" if (opts[:between] && opts[:between].size == 2)
         
     | 
| 
      
 818 
     | 
    
         
            +
             
     | 
| 
      
 819 
     | 
    
         
            +
                  arr_opts
         
     | 
| 
      
 820 
     | 
    
         
            +
                end
         
     | 
| 
      
 821 
     | 
    
         
            +
                
         
     | 
| 
      
 822 
     | 
    
         
            +
                # Retrurns an array holding path options for the log commands
         
     | 
| 
      
 823 
     | 
    
         
            +
                #
         
     | 
| 
      
 824 
     | 
    
         
            +
                # @param [Hash] opts the given options
         
     | 
| 
      
 825 
     | 
    
         
            +
                # @return [Array] the set of path options that the log command will use
         
     | 
| 
      
 826 
     | 
    
         
            +
                def log_path_options(opts)
         
     | 
| 
      
 827 
     | 
    
         
            +
                  arr_opts = []
         
     | 
| 
      
 828 
     | 
    
         
            +
                 
         
     | 
| 
      
 829 
     | 
    
         
            +
                  arr_opts << opts[:object] if opts[:object].is_a? String
         
     | 
| 
      
 830 
     | 
    
         
            +
                  arr_opts << '--' << opts[:path_limiter] if opts[:path_limiter]
         
     | 
| 
      
 831 
     | 
    
         
            +
             
     | 
| 
      
 832 
     | 
    
         
            +
                  arr_opts
         
     | 
| 
      
 833 
     | 
    
         
            +
                end
         
     | 
| 
      
 834 
     | 
    
         
            +
                
         
     | 
| 
      
 835 
     | 
    
         
            +
                def run_command(git_cmd, &block)
         
     | 
| 
      
 836 
     | 
    
         
            +
                  if block_given?
         
     | 
| 
      
 837 
     | 
    
         
            +
                    IO.popen(git_cmd, &block)
         
     | 
| 
      
 838 
     | 
    
         
            +
                  else
         
     | 
| 
      
 839 
     | 
    
         
            +
                    `#{git_cmd}`.chomp
         
     | 
| 
      
 840 
     | 
    
         
            +
                  end
         
     | 
| 
      
 841 
     | 
    
         
            +
                end
         
     | 
| 
      
 842 
     | 
    
         
            +
             
     | 
| 
      
 843 
     | 
    
         
            +
                def escape(s)
         
     | 
| 
      
 844 
     | 
    
         
            +
                  "'#{s && s.to_s.gsub('\'','\'"\'"\'')}'"
         
     | 
| 
      
 845 
     | 
    
         
            +
                end
         
     | 
| 
      
 846 
     | 
    
         
            +
             
     | 
| 
      
 847 
     | 
    
         
            +
              end
         
     | 
| 
      
 848 
     | 
    
         
            +
            end
         
     |