Class: Maximus::GitControl

Inherits:
Object
  • Object
show all
Includes:
Helper
Defined in:
lib/maximus/git_control.rb

Overview

Since:

  • 0.1.0

Instance Method Summary collapse

Methods included from Helper

#check_default_config_path, #edit_yaml, #file_count, #file_list, #is_rails?, #lines_added_to_range, #node_module_exists, #path_exists, #prompt, #reporter_path, #root_dir, #truthy

Constructor Details

#initialize(opts = {}) ⇒ void

Git management

Inherits settings from Config#initialize

Options Hash (opts):

  • :is_dev (Boolean) — default: false

    whether or not the class was initialized from the command line This is set here again in case only GitControl needs to be directly called (outside of command line)

  • :config (Config object)

    custom Maximus::Config object

  • :commit (String)

    accepts sha, “working”, “last”, or “master”.

Since:

  • 0.1.0


18
19
20
21
22
23
24
25
26
# File 'lib/maximus/git_control.rb', line 18

def initialize(opts = {})
  opts[:is_dev] ||= false

  opts[:config] ||= Maximus::Config.new({commit: opts[:commit], is_dev: opts[:is_dev] })
  @config ||= opts[:config]
  @settings ||= @config.settings
  @psuedo_commit = (!@settings[:commit].blank? && (@settings[:commit] == 'working' || @settings[:commit] == 'last' || @settings[:commit] == 'master') )
  @g = Git.open(@settings[:root_dir], :log => @settings[:git_log])
end

Instance Method Details

#commit_export(commitsha = sha) ⇒ Hash

30,000 foot view of a commit

Since:

  • 0.1.0


32
33
34
35
36
37
38
39
40
41
42
43
44
# File 'lib/maximus/git_control.rb', line 32

def commit_export(commitsha = sha)
  ce_commit = vccommit(commitsha)
  ce_diff = diff(ce_commit, @g.object('HEAD^'))
  {
    commitsha: commitsha,
    branch: branch,
    message: ce_commit.message,
    remote_repo: remote,
    git_author: ce_commit.author.name,
    git_author_email: ce_commit.author.email,
    diff: ce_diff
  }
end

#compare(sha1 = master_commit.sha, sha2 = sha) ⇒ Hash

Compare two commits and get line number ranges of changed patches

Examples:

output from the method

{
  'sha': {
    rb: {
      filename: 'file.rb',
      changes: {
        ['0..4'],
        ['10..20']
      }
    }
  }
}

Since:

  • 0.1.0


62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/maximus/git_control.rb', line 62

def compare(sha1 = master_commit.sha, sha2 = sha)
  diff_return = {}

  if @settings[:commit]
    sha1 = case @settings[:commit]
      when 'master' then master_commit.sha
      when 'last' then @g.object('HEAD^').sha
      when 'working' then 'working'
      else @settings[:commit]
    end
  end

  # If working directory, just have a single item array.
  #   The space here is important because git-lines checks for a second arg,
  #   and if one is present, it runs git diff without a commit
  #   or a comparison to a commit.
  git_diff = @psuedo_commit ? ['working directory'] : `git rev-list #{sha1}..#{sha2} --no-merges`.split("\n")

  # Include the first sha because rev-list is doing a traversal
  # So sha1 is never included
  git_diff << sha1 unless @psuedo_commit

  # Reverse so that we go in chronological order
  git_diff.reverse.each do |git_sha|
    new_lines = lines_added(git_sha)

    # Grab all files in that commit and group them by extension
    # If working copy, just give the diff names of the files changed
    files = @psuedo_commit ? `git diff --name-only` : `git show --pretty="format:" --name-only #{git_sha}`
    files = files.split("\n").group_by { |f| f.split('.').pop }

    # Don't worry about files that we don't have a lint or a statistic for
    flat_associations = associations.clone.flatten(2)
    files.delete_if { |k,v| !flat_associations.include?(k) || k.nil? }

    associations.each do |ext, related|
      files[ext] ||= []
      related.each do |child|
        unless files[child].blank?
          files[child].each do |c|
            # hack to ignore deleted files
            files[child] = new_lines[c].blank? ? [] : [ filename: "#{@settings[:root_dir]}/#{c}", changes: new_lines[c] ]
          end
          files[ext].concat(files[child])
          files.delete(child)
        end
      end
    end
    files.delete_if { |k,v| v.blank? }
    diff_return[git_sha.to_sym] = files
  end
  diff_return
end

#lints_and_stats(lint_by_path = false, git_shas = compare) ⇒ Hash

Run appropriate lint for every sha in commit history. For each sha a new branch is created then deleted

Examples:

sample output

{
  'sha': {
    lints: {
      scsslint: {
        files_inspec...
      },
    },
    statisti...
  },
  'sha'...
}

Since:

  • 0.1.0


133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
# File 'lib/maximus/git_control.rb', line 133

def lints_and_stats(lint_by_path = false, git_shas = compare)
  return false if git_shas.blank?
  base_branch = branch
  git_output = {}
  git_shas.each do |sha, exts|
    # @todo better way to silence git, in case there's a real error?
    quietly { `git checkout #{sha} -b maximus_#{sha}` } unless @psuedo_commit
    puts sha.to_s.color(:blue) if @config.is_dev?
    git_output[sha.to_sym] = {
      lints: {},
      statistics: {}
    }
    lints = git_output[sha.to_sym][:lints]
    statistics = git_output[sha.to_sym][:statistics]
    lint_opts = {}

    # This is where everything goes down
    exts.each do |ext, files|
      # For relevant_lines data
      lint_opts = {
        git_files: files,
        config: @config
      }
      lint_opts[:file_paths] = lint_file_paths(files, ext) if lint_by_path
      case ext
        when :scss
          lints[:scsslint] = Maximus::Scsslint.new(lint_opts).result

          # Do not run statistics if called from command line
          if lint_opts[:commit].blank?

            # @todo stylestat is singular here because model name in Rails is singular.
            #   But adding a .classify when it's converted to a model chops off the end s on 'phantomas',
            #   which breaks the model name.
            statistics[:stylestat] = Maximus::Stylestats.new({config: @config}).result

            # @todo double pipe here is best way to say, if it's already run, don't run again, right?
            statistics[:phantomas] ||= Maximus::Phantomas.new({config: @config}).result
            statistics[:wraith] ||= Maximus::Wraith.new({config: @config}).result
          end
        when :js
          lints[:jshint] = Maximus::Jshint.new(lint_opts).result

          # Do not run statistics if called from command line
          if lint_opts[:commit].blank?

            statistics[:phantomas] ||= Maximus::Phantomas.new({config: @config}).result

            # @todo double pipe here is best way to say, if it's already run, don't run again, right?
            statistics[:wraith] ||= Maximus::Wraith.new({config: @config}).result
          end
        when :ruby
          lints[:rubocop] = Maximus::Rubocop.new(lint_opts).result
          lints[:railsbp] ||= Maximus::Railsbp.new(lint_opts).result
          lints[:brakeman] = Maximus::Brakeman.new(lint_opts).result
        when :rails
          lints[:railsbp] ||= Maximus::Railsbp.new(lint_opts).result
      end
    end    # @todo better way to silence git, in case there's a real error?

    quietly {
      @g.branch(base_branch).checkout
      @g.branch("maximus_#{sha}").delete
    } unless @psuedo_commit
  end
  git_output
end