git_sme 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,149 @@
1
+ require 'fileutils'
2
+ require 'yaml'
3
+
4
+ require 'rugged'
5
+
6
+ require_relative 'cache'
7
+
8
+ module GitSme
9
+ class CommitLoader
10
+ attr_reader :valid, :error_message, :branch, :commits, :loaded, :repo
11
+
12
+ alias_method :valid?, :valid
13
+ alias_method :loaded?, :loaded
14
+
15
+ def initialize(path_to_repo, branch: 'master', enable_cache: true)
16
+ @branch = branch
17
+ @enable_cache = enable_cache
18
+ @commits = []
19
+ @loaded = false
20
+ @valid = true
21
+
22
+ begin
23
+ @repo = Rugged::Repository.new(File.expand_path(path_to_repo))
24
+ @branch = 'master' if @repo.branches[@branch].nil?
25
+
26
+ @cache = GitSme::Cache.new(@repo.path.gsub('/.git/', ''),
27
+ enabled: @enable_cache, file_suffix: "#{@branch}-commits"
28
+ )
29
+ rescue Rugged::RepositoryError => e
30
+ @valid = false
31
+ @error_message = e.message
32
+ end
33
+ end
34
+
35
+ def load(force: false)
36
+ return unless valid?
37
+ return if loaded? && !force
38
+
39
+ @commits = @cache.load
40
+ @last_commit_idx = @commits.size - 1
41
+ @commit_count = `cd #{@repo.path.gsub('/.git/', '')} && git rev-list --count #{@branch}`.to_i
42
+
43
+ walker = Rugged::Walker.new(@repo)
44
+ walker.push(@repo.branches[@branch].target_id)
45
+
46
+ if @enable_cache && @commits.size > 0
47
+ appending_to_cache = true
48
+ oldest_cached_commit = @commits[-1]
49
+ oldest_cached_commit_sha = oldest_cached_commit ? oldest_cached_commit[:sha1] : nil
50
+
51
+ walker.sorting(Rugged::SORT_REVERSE)
52
+ end
53
+
54
+ new_commits = []
55
+
56
+ walker.each do |commit|
57
+ break if appending_to_cache && commit.oid == oldest_cached_commit_sha
58
+
59
+ process_commit(appending_to_cache, commit, new_commits) do |new_commit_count, processed_commit_count, all_commit_count|
60
+ yield(new_commit_count, processed_commit_count, all_commit_count)
61
+ end
62
+ end
63
+
64
+ walker.reset
65
+
66
+ @commits.concat(new_commits.reverse) if new_commits.any?
67
+
68
+ @cache.save(@commits)
69
+
70
+ @loaded = true
71
+ end
72
+
73
+ def load!
74
+ load(force: true)
75
+ end
76
+ alias_method :reload!, :load!
77
+
78
+ def new_commits?
79
+ return false if @last_commit_idx.nil?
80
+
81
+ @last_commit_idx > 0 && @last_commit_idx < (@commits.size - 1)
82
+ end
83
+
84
+ def new_commits
85
+ return [] unless new_commits?
86
+
87
+ @commits.slice(@last_commit_idx, @commits.size)
88
+ end
89
+
90
+ private
91
+
92
+ def process_commit(appending_to_cache, commit, new_commits)
93
+ return if merge_commit?(commit)
94
+
95
+ commit_details = get_commit_details(commit)
96
+
97
+ if appending_to_cache
98
+ new_commits << commit_details
99
+ else
100
+ @commits << commit_details
101
+ end
102
+
103
+ # To aid in tracking progress since this process can take some time
104
+ yield(new_commits.size, @commits.size, @commit_count) if block_given?
105
+ end
106
+
107
+ def merge_commit?(commit)
108
+ commit.parents.size > 1
109
+ end
110
+
111
+ def get_patch_details(patch)
112
+ filename = patch.header.split("\n")[0].split[-1].split('/', 2)[-1]
113
+ additions, deletions = patch.stat
114
+
115
+ {
116
+ filename => {
117
+ additions: additions,
118
+ deletions: deletions,
119
+ changes: patch.changes
120
+ }
121
+ }
122
+ end
123
+
124
+ def get_commit_details(commit)
125
+ patches = commit.diff(commit.parents.first)
126
+ additions = deletions = 0
127
+ file_changes = patches.each_with_object({}) do |patch, hash|
128
+ patch_details = get_patch_details(patch)
129
+ changes = patch_details.values.first
130
+
131
+ hash.merge!(patch_details)
132
+
133
+ additions += changes[:additions]
134
+ deletions += changes[:deletions]
135
+ end
136
+
137
+ {
138
+ sha1: commit.oid,
139
+ timestamp: commit.epoch_time,
140
+ author: commit.author[:email].split('@')[0],
141
+ files_changed: file_changes.keys.size,
142
+ file_changes: file_changes,
143
+ additions: additions,
144
+ deletions: deletions,
145
+ changes: additions + deletions
146
+ }
147
+ end
148
+ end
149
+ end
@@ -0,0 +1,3 @@
1
+ module GitSme
2
+ PREFERENCES_HOME=File.join([Dir.home(), '.gitsme'])
3
+ end
@@ -0,0 +1,3 @@
1
+ module GitSme
2
+ VERSION = '0.1.0'
3
+ end
metadata ADDED
@@ -0,0 +1,151 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: git_sme
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Shahbaz Javeed
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2017-08-15 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.15'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.15'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.2'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.2'
55
+ - !ruby/object:Gem::Dependency
56
+ name: ruby-progressbar
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rugged
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: thor
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ description: Analyze your git repository and determine subject matter experts by identifying
98
+ everyone who has touched a file with preference given to recent touches
99
+ email:
100
+ - sjaveed@gmail.com
101
+ executables:
102
+ - git-sme
103
+ extensions: []
104
+ extra_rdoc_files: []
105
+ files:
106
+ - ".gitignore"
107
+ - ".rspec"
108
+ - ".travis.yml"
109
+ - CODE_OF_CONDUCT.md
110
+ - Gemfile
111
+ - Gemfile.lock
112
+ - LICENSE
113
+ - README.md
114
+ - Rakefile
115
+ - bin/console
116
+ - bin/setup
117
+ - exe/git-sme
118
+ - git_sme.gemspec
119
+ - lib/git_sme.rb
120
+ - lib/git_sme/analysis_presenter.rb
121
+ - lib/git_sme/cache.rb
122
+ - lib/git_sme/cli.rb
123
+ - lib/git_sme/commit_analyzer.rb
124
+ - lib/git_sme/commit_loader.rb
125
+ - lib/git_sme/preferences.rb
126
+ - lib/git_sme/version.rb
127
+ homepage: https://github.com/sjaveed/git_sme
128
+ licenses:
129
+ - MIT
130
+ metadata: {}
131
+ post_install_message:
132
+ rdoc_options: []
133
+ require_paths:
134
+ - lib
135
+ required_ruby_version: !ruby/object:Gem::Requirement
136
+ requirements:
137
+ - - ">="
138
+ - !ruby/object:Gem::Version
139
+ version: '0'
140
+ required_rubygems_version: !ruby/object:Gem::Requirement
141
+ requirements:
142
+ - - ">="
143
+ - !ruby/object:Gem::Version
144
+ version: '0'
145
+ requirements: []
146
+ rubyforge_project:
147
+ rubygems_version: 2.6.11
148
+ signing_key:
149
+ specification_version: 4
150
+ summary: Identify subject matter experts by analyzing your git repository
151
+ test_files: []