meta_commit 0.1.0.alpha → 0.2.0.pre.alpha
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 +4 -4
- data/.travis.yml +3 -0
- data/CONTRIBUTING.md +61 -0
- data/README.md +36 -5
- data/Rakefile +7 -1
- data/config/default.yml +11 -0
- data/exe/meta_commit +5 -1
- data/lib/meta_commit/changelog/adapters/changelog.rb +94 -0
- data/lib/meta_commit/changelog/commands/commit_diff_examiner.rb +50 -0
- data/lib/meta_commit/changelog/formatters/keep_a_changelog_ver_report_builder.rb +123 -0
- data/lib/meta_commit/cli.rb +71 -17
- data/lib/meta_commit/configuration.rb +45 -0
- data/lib/meta_commit/configuration_store.rb +27 -0
- data/lib/meta_commit/container.rb +80 -0
- data/lib/meta_commit/errors.rb +12 -0
- data/lib/meta_commit/factories/contextual_ast_node_factory.rb +61 -0
- data/lib/meta_commit/factories/diff_factory.rb +37 -0
- data/lib/meta_commit/factories/parser_factory.rb +30 -0
- data/lib/meta_commit/git/repo.rb +124 -2
- data/lib/meta_commit/index/adapters/git_notes.rb +34 -0
- data/lib/meta_commit/index/commands/diff_examiner.rb +58 -0
- data/lib/meta_commit/message/commands/diff_index_examiner.rb +48 -0
- data/lib/meta_commit/message/formatters/commit_message_builder.rb +16 -0
- data/lib/meta_commit/models/changes/commit.rb +24 -0
- data/lib/meta_commit/models/changes/repository.rb +12 -0
- data/lib/meta_commit/models/contextual_ast_node.rb +9 -0
- data/lib/meta_commit/models/diffs/diff.rb +31 -3
- data/lib/meta_commit/services/change_saver.rb +3 -26
- data/lib/meta_commit/services/parse.rb +21 -0
- data/lib/meta_commit/version.rb +1 -1
- data/lib/meta_commit.rb +34 -27
- data/meta_commit.gemspec +5 -0
- metadata +90 -23
- data/lib/meta_commit/adapters/dump.rb +0 -31
- data/lib/meta_commit/adapters/git_notes.rb +0 -28
- data/lib/meta_commit/models/ast_path.rb +0 -111
- data/lib/meta_commit/models/changes/file.rb +0 -27
- data/lib/meta_commit/models/diffs/addition.rb +0 -34
- data/lib/meta_commit/models/diffs/changes_in_method.rb +0 -14
- data/lib/meta_commit/models/diffs/class_creation.rb +0 -20
- data/lib/meta_commit/models/diffs/class_deletion.rb +0 -16
- data/lib/meta_commit/models/diffs/class_rename.rb +0 -11
- data/lib/meta_commit/models/diffs/deletion.rb +0 -37
- data/lib/meta_commit/models/diffs/method_creation.rb +0 -22
- data/lib/meta_commit/models/diffs/method_deletion.rb +0 -22
- data/lib/meta_commit/models/diffs/module_creation.rb +0 -14
- data/lib/meta_commit/models/diffs/module_deletion.rb +0 -14
- data/lib/meta_commit/models/diffs/module_rename.rb +0 -11
- data/lib/meta_commit/models/diffs/replacement.rb +0 -19
- data/lib/meta_commit/models/factories/ast_path_factory.rb +0 -40
- data/lib/meta_commit/models/factories/diff_factory.rb +0 -39
- data/lib/meta_commit/services/commit_message_builder.rb +0 -23
- data/lib/meta_commit/services/diff_examiner.rb +0 -121
- data/lib/meta_commit/services/diff_index_examiner.rb +0 -112
@@ -1,11 +0,0 @@
|
|
1
|
-
module MetaCommit::Models::Diffs
|
2
|
-
class ClassRename < Diff
|
3
|
-
def supports_change(type, old_file_name, new_file_name, old_ast_path, new_ast_path)
|
4
|
-
type == MetaCommit::Models::Diffs::Diff::TYPE_REPLACE && !old_ast_path.nil? && !new_ast_path.nil? && old_ast_path.is_name_of_class? && new_ast_path.is_name_of_class?
|
5
|
-
end
|
6
|
-
|
7
|
-
def string_representation
|
8
|
-
"renamed class #{old_ast_path.name_of_context_class} to #{new_ast_path.name_of_context_class}"
|
9
|
-
end
|
10
|
-
end
|
11
|
-
end
|
@@ -1,37 +0,0 @@
|
|
1
|
-
module MetaCommit::Models::Diffs
|
2
|
-
class Deletion < Diff
|
3
|
-
def string_representation
|
4
|
-
action = 'removed'
|
5
|
-
if @old_ast_path.is_module?
|
6
|
-
return "#{action} module #{old_ast_path.module_name}"
|
7
|
-
end
|
8
|
-
if @old_ast_path.is_name_of_module?
|
9
|
-
return "#{action} module #{old_ast_path.name_of_context_module}"
|
10
|
-
end
|
11
|
-
if @old_ast_path.is_class?
|
12
|
-
if @_ast_path.is_in_context_of_module?
|
13
|
-
return "#{action} #{name_of_context_module}::#{new_ast_path.class_name}"
|
14
|
-
end
|
15
|
-
return "#{action} class #{old_ast_path.class_name}"
|
16
|
-
end
|
17
|
-
if @old_ast_path.is_name_of_class?
|
18
|
-
return "#{action} class #{old_ast_path.name_of_context_class}"
|
19
|
-
end
|
20
|
-
if @old_ast_path.is_method?
|
21
|
-
if @old_ast_path.is_in_context_of_class?
|
22
|
-
return "#{action} #{old_ast_path.name_of_context_class}##{old_ast_path.method_name}"
|
23
|
-
end
|
24
|
-
if @old_ast_path.is_in_context_of_module?
|
25
|
-
if @old_ast_path.is_in_context_of_class?
|
26
|
-
return "#{action} #{old_ast_path.name_of_context_module}::#{old_ast_path.name_of_context_class}##{old_ast_path.method_name}"
|
27
|
-
end
|
28
|
-
return "#{action} method #{old_ast_path.method_name} from module #{old_ast_path.name_of_context_module}"
|
29
|
-
end
|
30
|
-
end
|
31
|
-
if @old_ast_path.is_in_context_of_method?
|
32
|
-
return "changes in method #{@old_ast_path.name_of_context_method}"
|
33
|
-
end
|
34
|
-
'deletion was performed'
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
@@ -1,22 +0,0 @@
|
|
1
|
-
module MetaCommit::Models::Diffs
|
2
|
-
class MethodCreation < Diff
|
3
|
-
def supports_change(type, old_file_name, new_file_name, old_ast_path, new_ast_path)
|
4
|
-
type == MetaCommit::Models::Diffs::Diff::TYPE_ADDITION && !new_ast_path.empty_ast? && (new_ast_path.is_method? || new_ast_path.is_in_context_of_method?)
|
5
|
-
end
|
6
|
-
|
7
|
-
def string_representation
|
8
|
-
if @new_ast_path.is_method?
|
9
|
-
if @new_ast_path.is_in_context_of_module?
|
10
|
-
if @new_ast_path.is_in_context_of_class?
|
11
|
-
return "created #{new_ast_path.name_of_context_module}::#{new_ast_path.name_of_context_class}##{new_ast_path.method_name}"
|
12
|
-
end
|
13
|
-
return "created #{new_ast_path.name_of_context_module}##{new_ast_path.method_name}"
|
14
|
-
end
|
15
|
-
if @new_ast_path.is_in_context_of_class?
|
16
|
-
return "created #{new_ast_path.name_of_context_class}##{new_ast_path.method_name}"
|
17
|
-
end
|
18
|
-
end
|
19
|
-
"changes in method #{new_ast_path.name_of_context_method}"
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
@@ -1,22 +0,0 @@
|
|
1
|
-
module MetaCommit::Models::Diffs
|
2
|
-
class MethodDeletion < Diff
|
3
|
-
def supports_change(type, old_file_name, new_file_name, old_ast_path, new_ast_path)
|
4
|
-
type == MetaCommit::Models::Diffs::Diff::TYPE_DELETION && !old_ast_path.empty_ast? && (old_ast_path.is_method? || old_ast_path.is_in_context_of_method?)
|
5
|
-
end
|
6
|
-
|
7
|
-
def string_representation
|
8
|
-
if @old_ast_path.is_method?
|
9
|
-
if @old_ast_path.is_in_context_of_module?
|
10
|
-
if @old_ast_path.is_in_context_of_class?
|
11
|
-
return "removed #{old_ast_path.name_of_context_module}::#{old_ast_path.name_of_context_class}##{old_ast_path.method_name}"
|
12
|
-
end
|
13
|
-
return "removed method #{old_ast_path.method_name} from module #{old_ast_path.name_of_context_module}"
|
14
|
-
end
|
15
|
-
if @old_ast_path.is_in_context_of_class?
|
16
|
-
return "removed #{old_ast_path.name_of_context_class}##{old_ast_path.method_name}"
|
17
|
-
end
|
18
|
-
end
|
19
|
-
"changes in method #{old_ast_path.name_of_context_method}"
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
@@ -1,14 +0,0 @@
|
|
1
|
-
module MetaCommit::Models::Diffs
|
2
|
-
class ModuleCreation < Diff
|
3
|
-
def supports_change(type, old_file_name, new_file_name, old_ast_path, new_ast_path)
|
4
|
-
type == MetaCommit::Models::Diffs::Diff::TYPE_ADDITION && !new_ast_path.empty_ast? && (new_ast_path.is_module? || new_ast_path.is_name_of_module?)
|
5
|
-
end
|
6
|
-
|
7
|
-
def string_representation
|
8
|
-
if @new_ast_path.is_module?
|
9
|
-
return "created module #{new_ast_path.module_name}"
|
10
|
-
end
|
11
|
-
"created module #{new_ast_path.name_of_context_module}"
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
@@ -1,14 +0,0 @@
|
|
1
|
-
module MetaCommit::Models::Diffs
|
2
|
-
class ModuleDeletion < Diff
|
3
|
-
def supports_change(type, old_file_name, new_file_name, old_ast_path, new_ast_path)
|
4
|
-
type == MetaCommit::Models::Diffs::Diff::TYPE_DELETION && !old_ast_path.empty_ast? && (old_ast_path.is_module? || old_ast_path.is_name_of_module?)
|
5
|
-
end
|
6
|
-
|
7
|
-
def string_representation
|
8
|
-
if @old_ast_path.is_module?
|
9
|
-
return "removed module #{old_ast_path.module_name}"
|
10
|
-
end
|
11
|
-
"removed module #{old_ast_path.name_of_context_module}"
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
@@ -1,11 +0,0 @@
|
|
1
|
-
module MetaCommit::Models::Diffs
|
2
|
-
class ModuleRename < Diff
|
3
|
-
def supports_change(type, old_file_name, new_file_name, old_ast_path, new_ast_path)
|
4
|
-
type == MetaCommit::Models::Diffs::Diff::TYPE_REPLACE && !old_ast_path.empty_ast? && !new_ast_path.empty_ast? && old_ast_path.is_name_of_module? && new_ast_path.is_name_of_module?
|
5
|
-
end
|
6
|
-
|
7
|
-
def string_representation
|
8
|
-
"renamed module #{old_ast_path.name_of_context_module} to #{new_ast_path.name_of_context_module}"
|
9
|
-
end
|
10
|
-
end
|
11
|
-
end
|
@@ -1,19 +0,0 @@
|
|
1
|
-
module MetaCommit::Models::Diffs
|
2
|
-
class Replacement < Diff
|
3
|
-
def string_representation
|
4
|
-
if @old_ast_path.is_name_of_module? && @new_ast_path.is_name_of_module?
|
5
|
-
return "renamed module #{old_ast_path.name_of_context_module} to #{new_ast_path.name_of_context_module}"
|
6
|
-
end
|
7
|
-
if @old_ast_path.is_name_of_class? && @new_ast_path.is_name_of_class?
|
8
|
-
return "renamed class #{old_ast_path.name_of_context_class} to #{new_ast_path.name_of_context_class}"
|
9
|
-
end
|
10
|
-
if @old_ast_path.is_in_context_of_method? && @new_ast_path.is_in_context_of_method?
|
11
|
-
if @new_ast_path.is_in_context_of_class?
|
12
|
-
return "changes in #{new_ast_path.name_of_context_class}##{new_ast_path.name_of_context_method}"
|
13
|
-
end
|
14
|
-
return "changes in ##{new_ast_path.name_of_context_method}"
|
15
|
-
end
|
16
|
-
'replacing was performed'
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
@@ -1,40 +0,0 @@
|
|
1
|
-
module MetaCommit::Models::Factories
|
2
|
-
class AstPathFactory
|
3
|
-
def create_ast_path(source_ast, line_number)
|
4
|
-
visited_nodes = []
|
5
|
-
ast_path = MetaCommit::Models::AstPath.new
|
6
|
-
ast_path.ast = collect_path_to_ast_at_line(source_ast, line_number, visited_nodes)
|
7
|
-
ast_path.path = visited_nodes
|
8
|
-
ast_path
|
9
|
-
end
|
10
|
-
|
11
|
-
protected
|
12
|
-
def get_ast_at_line(ast, lineno)
|
13
|
-
return nil unless ast_covers_line(ast, lineno)
|
14
|
-
closest_ast = ast
|
15
|
-
ast.children.each do |child|
|
16
|
-
found_ast = get_ast_at_line(child, lineno)
|
17
|
-
closest_ast = found_ast unless found_ast.nil?
|
18
|
-
end
|
19
|
-
closest_ast
|
20
|
-
end
|
21
|
-
|
22
|
-
protected
|
23
|
-
def collect_path_to_ast_at_line(ast, lineno, accumulator)
|
24
|
-
return nil unless ast_covers_line(ast, lineno)
|
25
|
-
closest_ast = ast
|
26
|
-
accumulator.push(closest_ast)
|
27
|
-
ast.children.each do |child|
|
28
|
-
found_ast = collect_path_to_ast_at_line(child, lineno, accumulator)
|
29
|
-
closest_ast = found_ast unless found_ast.nil?
|
30
|
-
end
|
31
|
-
closest_ast
|
32
|
-
end
|
33
|
-
|
34
|
-
protected
|
35
|
-
def ast_covers_line(ast, line)
|
36
|
-
return false unless (ast.respond_to?(:loc) && ast.loc.respond_to?(:expression) && !ast.loc.expression.nil?)
|
37
|
-
(ast.loc.first_line <= line) && (ast.loc.last_line >= line)
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
@@ -1,39 +0,0 @@
|
|
1
|
-
module MetaCommit::Models::Factories
|
2
|
-
class DiffFactory
|
3
|
-
attr_accessor :available_diff_classes
|
4
|
-
|
5
|
-
def initialize
|
6
|
-
@available_diff_classes = [
|
7
|
-
MetaCommit::Models::Diffs::ClassCreation,
|
8
|
-
MetaCommit::Models::Diffs::ClassDeletion,
|
9
|
-
MetaCommit::Models::Diffs::ClassRename,
|
10
|
-
MetaCommit::Models::Diffs::MethodCreation,
|
11
|
-
MetaCommit::Models::Diffs::MethodDeletion,
|
12
|
-
MetaCommit::Models::Diffs::ChangesInMethod,
|
13
|
-
MetaCommit::Models::Diffs::ModuleCreation,
|
14
|
-
MetaCommit::Models::Diffs::ModuleDeletion,
|
15
|
-
MetaCommit::Models::Diffs::ModuleRename,
|
16
|
-
MetaCommit::Models::Diffs::Diff,
|
17
|
-
]
|
18
|
-
end
|
19
|
-
|
20
|
-
def create_diff_of_type(type, options)
|
21
|
-
@available_diff_classes.each do |diff_class|
|
22
|
-
diff = diff_class.new
|
23
|
-
if diff.supports_change(type, options[:old_file_path], options[:new_file_path], options[:old_ast_path], options[:new_ast_path])
|
24
|
-
line = options[:line]
|
25
|
-
diff.diff_type = line.line_origin
|
26
|
-
diff.commit_old = options[:commit_id_old]
|
27
|
-
diff.commit_new = options[:commit_id_new]
|
28
|
-
diff.old_file = options[:old_file_path]
|
29
|
-
diff.new_file = options[:new_file_path]
|
30
|
-
diff.old_lineno = line.old_lineno
|
31
|
-
diff.new_lineno = line.new_lineno
|
32
|
-
diff.old_ast_path = options[:old_ast_path]
|
33
|
-
diff.new_ast_path = options[:new_ast_path]
|
34
|
-
return diff
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
@@ -1,23 +0,0 @@
|
|
1
|
-
module MetaCommit::Services
|
2
|
-
class CommitMessageBuilder
|
3
|
-
attr_accessor :repo
|
4
|
-
|
5
|
-
def initialize(repo)
|
6
|
-
@repo = repo
|
7
|
-
end
|
8
|
-
|
9
|
-
def build(commit_change)
|
10
|
-
message = []
|
11
|
-
commit_change.each do |file_change|
|
12
|
-
file_change.each do |diff|
|
13
|
-
message.push(build_message_for_diff(diff))
|
14
|
-
end
|
15
|
-
end
|
16
|
-
message.join("\n")
|
17
|
-
end
|
18
|
-
|
19
|
-
def build_message_for_diff(diff)
|
20
|
-
diff.to_s
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
@@ -1,121 +0,0 @@
|
|
1
|
-
require "parser/current"
|
2
|
-
|
3
|
-
module MetaCommit::Services
|
4
|
-
class DiffExaminer
|
5
|
-
DIFF_OPTIONS = {:context_lines => 0, :ignore_whitespace => true}
|
6
|
-
FILE_NOT_EXISTS_OID = '0000000000000000000000000000000000000000'
|
7
|
-
|
8
|
-
def initialize(repo)
|
9
|
-
@repo = repo
|
10
|
-
end
|
11
|
-
|
12
|
-
# region meta
|
13
|
-
def meta
|
14
|
-
changes = MetaCommit::Models::Changes::Repository.new(@repo.repo.path)
|
15
|
-
@repo.walk_by_commits do |previous_commit, current_commit|
|
16
|
-
diff = @repo.diff(previous_commit, current_commit, DIFF_OPTIONS)
|
17
|
-
changes.push(examine_commits_diff(diff, previous_commit, current_commit))
|
18
|
-
end
|
19
|
-
changes
|
20
|
-
end
|
21
|
-
|
22
|
-
def examine_commits_diff(diff, commit_old, commit_new)
|
23
|
-
old_id = commit_old.oid
|
24
|
-
new_id = commit_new.oid
|
25
|
-
diffs = MetaCommit::Models::Changes::Commit.new(old_id, new_id)
|
26
|
-
diff.deltas.zip(diff.patches).each do |delta, patch|
|
27
|
-
# file check here
|
28
|
-
# build parser using factory and pass like argument
|
29
|
-
diffs.push(examine_delta(delta, patch, old_id, new_id))
|
30
|
-
end
|
31
|
-
diffs
|
32
|
-
end
|
33
|
-
|
34
|
-
def examine_delta(delta, patch, commit_id_old, commit_id_new)
|
35
|
-
old_file_path = delta.old_file[:path]
|
36
|
-
new_file_path = delta.new_file[:path]
|
37
|
-
|
38
|
-
diffs = MetaCommit::Models::Changes::File.new(old_file_path, new_file_path)
|
39
|
-
|
40
|
-
return diffs unless (can_examine(old_file_path) and can_examine(new_file_path))
|
41
|
-
|
42
|
-
old_file_content = @repo.get_blob_at(commit_id_old, old_file_path, '')
|
43
|
-
new_file_content = @repo.get_blob_at(commit_id_new, new_file_path, '')
|
44
|
-
|
45
|
-
begin
|
46
|
-
old_file_ast = Parser::CurrentRuby.parse(old_file_content)
|
47
|
-
new_file_ast = Parser::CurrentRuby.parse(new_file_content)
|
48
|
-
rescue Parser::SyntaxError
|
49
|
-
return diffs
|
50
|
-
end
|
51
|
-
|
52
|
-
lines_to_walk = organize_lines(delta, patch)
|
53
|
-
|
54
|
-
lines_to_walk.each do |line|
|
55
|
-
old_ast_path = MetaCommit::Models::Factories::AstPathFactory.new.create_ast_path(old_file_ast, line.old_lineno)
|
56
|
-
new_ast_path = MetaCommit::Models::Factories::AstPathFactory.new.create_ast_path(new_file_ast, line.new_lineno)
|
57
|
-
|
58
|
-
factory = MetaCommit::Models::Factories::DiffFactory.new
|
59
|
-
diff = factory.create_diff_of_type(line.line_origin, {
|
60
|
-
:line => line,
|
61
|
-
:commit_id_old => commit_id_old,
|
62
|
-
:commit_id_new => commit_id_new,
|
63
|
-
:old_ast_path => old_ast_path,
|
64
|
-
:new_ast_path => new_ast_path,
|
65
|
-
:old_file_path => old_file_path,
|
66
|
-
:new_file_path => new_file_path,
|
67
|
-
})
|
68
|
-
diffs.push(diff)
|
69
|
-
end
|
70
|
-
diffs
|
71
|
-
end
|
72
|
-
|
73
|
-
# endregion
|
74
|
-
|
75
|
-
# region helpers
|
76
|
-
def can_examine(file_path)
|
77
|
-
file_path.end_with?('.rb')
|
78
|
-
end
|
79
|
-
|
80
|
-
def organize_lines(delta, patch)
|
81
|
-
lines_to_walk = []
|
82
|
-
# if whole file was changed examine one time only
|
83
|
-
whole_file_changed = (delta.old_file[:oid] == FILE_NOT_EXISTS_OID) || (delta.new_file[:oid] == FILE_NOT_EXISTS_OID)
|
84
|
-
skip_walking = false
|
85
|
-
skip_next_line = false
|
86
|
-
patch.hunks.each_with_index do |hunk|
|
87
|
-
break if skip_walking
|
88
|
-
hunk.lines.each_with_index do |line, line_index|
|
89
|
-
break if skip_walking
|
90
|
-
|
91
|
-
if skip_next_line
|
92
|
-
skip_next_line = false
|
93
|
-
next
|
94
|
-
end
|
95
|
-
|
96
|
-
next_line = hunk.lines[line_index + 1]
|
97
|
-
is_replace_change = (line.deletion?) && (!next_line.nil? && next_line.addition?) && (line.old_lineno && next_line.new_lineno)
|
98
|
-
|
99
|
-
line_to_walk = MetaCommit::Models::Line.new
|
100
|
-
if is_replace_change
|
101
|
-
line_to_walk.line_origin=:replace
|
102
|
-
line_to_walk.old_lineno=line.old_lineno
|
103
|
-
line_to_walk.new_lineno=next_line.new_lineno
|
104
|
-
else
|
105
|
-
line_to_walk.line_origin=line.line_origin
|
106
|
-
line_to_walk.old_lineno=line.old_lineno
|
107
|
-
line_to_walk.new_lineno=line.new_lineno
|
108
|
-
end
|
109
|
-
if is_replace_change
|
110
|
-
skip_next_line = true
|
111
|
-
end
|
112
|
-
lines_to_walk.push(line_to_walk)
|
113
|
-
|
114
|
-
skip_walking = true if whole_file_changed
|
115
|
-
end
|
116
|
-
end
|
117
|
-
lines_to_walk
|
118
|
-
end
|
119
|
-
# endregion
|
120
|
-
end
|
121
|
-
end
|
@@ -1,112 +0,0 @@
|
|
1
|
-
require "parser/current"
|
2
|
-
|
3
|
-
module MetaCommit::Services
|
4
|
-
class DiffIndexExaminer
|
5
|
-
DIFF_OPTIONS = {:context_lines => 0, :ignore_whitespace => true}
|
6
|
-
FILE_NOT_EXISTS_OID = '0000000000000000000000000000000000000000'
|
7
|
-
|
8
|
-
def initialize(repo)
|
9
|
-
@repo = repo
|
10
|
-
end
|
11
|
-
|
12
|
-
# region index_meta
|
13
|
-
def index_meta
|
14
|
-
diff = @repo.index_diff(DIFF_OPTIONS)
|
15
|
-
|
16
|
-
diffs = MetaCommit::Models::Changes::Commit.new(@repo.repo.last_commit.oid, "staged")
|
17
|
-
|
18
|
-
diff.deltas.zip(diff.patches).each do |delta, patch|
|
19
|
-
diffs.push(examine_index_delta(delta, patch, @repo.repo.last_commit.oid))
|
20
|
-
end
|
21
|
-
diffs
|
22
|
-
end
|
23
|
-
|
24
|
-
def examine_index_delta(delta, patch, commit_id_old)
|
25
|
-
old_file_path = delta.old_file[:path]
|
26
|
-
new_file_path = delta.new_file[:path]
|
27
|
-
|
28
|
-
diffs = MetaCommit::Models::Changes::File.new(old_file_path, new_file_path)
|
29
|
-
|
30
|
-
return diffs unless (can_examine(old_file_path) and can_examine(new_file_path))
|
31
|
-
|
32
|
-
old_file_content = @repo.get_blob_at(commit_id_old, old_file_path, '')
|
33
|
-
# @TODO get content of staged changes only
|
34
|
-
new_file_content = @repo.get_content_of(new_file_path, '')
|
35
|
-
|
36
|
-
begin
|
37
|
-
old_file_ast = Parser::CurrentRuby.parse(old_file_content)
|
38
|
-
new_file_ast = Parser::CurrentRuby.parse(new_file_content)
|
39
|
-
rescue Parser::SyntaxError
|
40
|
-
return diffs
|
41
|
-
end
|
42
|
-
|
43
|
-
lines_to_walk = organize_lines(delta, patch)
|
44
|
-
|
45
|
-
lines_to_walk.each do |line|
|
46
|
-
old_ast_path = MetaCommit::Models::Factories::AstPathFactory.new.create_ast_path(old_file_ast, line.old_lineno)
|
47
|
-
new_ast_path = MetaCommit::Models::Factories::AstPathFactory.new.create_ast_path(new_file_ast, line.new_lineno)
|
48
|
-
|
49
|
-
factory = MetaCommit::Models::Factories::DiffFactory.new
|
50
|
-
diff = factory.create_diff_of_type(line.line_origin, {
|
51
|
-
:line => line,
|
52
|
-
:commit_id_old => commit_id_old,
|
53
|
-
:commit_id_new => 'workdir',
|
54
|
-
:old_ast_path => old_ast_path,
|
55
|
-
:new_ast_path => new_ast_path,
|
56
|
-
:old_file_path => old_file_path,
|
57
|
-
:new_file_path => new_file_path,
|
58
|
-
})
|
59
|
-
diffs.push(diff)
|
60
|
-
end
|
61
|
-
|
62
|
-
diffs
|
63
|
-
end
|
64
|
-
|
65
|
-
# endregion
|
66
|
-
|
67
|
-
# region helpers
|
68
|
-
def can_examine(file_path)
|
69
|
-
file_path.end_with?('.rb')
|
70
|
-
end
|
71
|
-
def organize_lines(delta, patch)
|
72
|
-
lines_to_walk = []
|
73
|
-
# if whole file was changed examine one time only
|
74
|
-
whole_file_changed = (delta.old_file[:oid] == FILE_NOT_EXISTS_OID) || (delta.new_file[:oid] == FILE_NOT_EXISTS_OID)
|
75
|
-
skip_walking = false
|
76
|
-
skip_next_line = false
|
77
|
-
patch.hunks.each_with_index do |hunk|
|
78
|
-
break if skip_walking
|
79
|
-
hunk.lines.each_with_index do |line, line_index|
|
80
|
-
break if skip_walking
|
81
|
-
|
82
|
-
if skip_next_line
|
83
|
-
skip_next_line = false
|
84
|
-
next
|
85
|
-
end
|
86
|
-
|
87
|
-
next_line = hunk.lines[line_index + 1]
|
88
|
-
is_replace_change = (line.deletion?) && (!next_line.nil? && next_line.addition?) && (line.old_lineno && next_line.new_lineno)
|
89
|
-
|
90
|
-
line_to_walk = MetaCommit::Models::Line.new
|
91
|
-
if is_replace_change
|
92
|
-
line_to_walk.line_origin=:replace
|
93
|
-
line_to_walk.old_lineno=line.old_lineno
|
94
|
-
line_to_walk.new_lineno=next_line.new_lineno
|
95
|
-
else
|
96
|
-
line_to_walk.line_origin=line.line_origin
|
97
|
-
line_to_walk.old_lineno=line.old_lineno
|
98
|
-
line_to_walk.new_lineno=line.new_lineno
|
99
|
-
end
|
100
|
-
if is_replace_change
|
101
|
-
skip_next_line = true
|
102
|
-
end
|
103
|
-
lines_to_walk.push(line_to_walk)
|
104
|
-
|
105
|
-
skip_walking = true if whole_file_changed
|
106
|
-
end
|
107
|
-
end
|
108
|
-
lines_to_walk
|
109
|
-
end
|
110
|
-
# endregion
|
111
|
-
end
|
112
|
-
end
|