commit_filter 0.0.1 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/assets/images/commit_filter/spinner.gif +0 -0
- data/app/assets/javascripts/commit_filter/file_commits.js.coffee +19 -0
- data/app/assets/javascripts/commit_filter/form.js.coffee +15 -0
- data/app/assets/javascripts/commit_filter/frameworks/twitter_bootstrap/3/filter_result.js.coffee +8 -0
- data/app/assets/stylesheets/commit_filter/base.css +15 -0
- data/app/assets/stylesheets/commit_filter/commit/diff.css +65 -0
- data/app/controllers/commit_filter/application_controller.rb +25 -0
- data/app/controllers/commit_filter/commit/diffs_controller.rb +24 -0
- data/app/controllers/commit_filter/commit/filters_controller.rb +28 -0
- data/app/helpers/commit_filter/application_helper.rb +55 -0
- data/app/models/commit_filter/model.rb +269 -0
- data/app/presenters/commit_filter/application_presenter.rb +9 -0
- data/app/presenters/commit_filter/presenter.rb +13 -0
- data/app/presenters/commit_filter/presenters/frameworks/twitter_bootstrap/version3_presenter.rb +51 -0
- data/app/views/commit_filter/frameworks/twitter_bootstrap/3/commit/filters/_categories.html.erb +28 -0
- data/app/views/commit_filter/frameworks/twitter_bootstrap/3/commit/filters/_file_commits.html.erb +68 -0
- data/app/views/commit_filter/frameworks/twitter_bootstrap/3/commit/filters/_files.html.erb +26 -0
- data/app/views/commit_filter/frameworks/twitter_bootstrap/3/commit/filters/_form.html.erb +80 -0
- data/app/views/commit_filter/frameworks/twitter_bootstrap/3/commit/filters/new.html.erb +24 -0
- data/app/views/commit_filter/frameworks/twitter_bootstrap/3/layouts/commit_filter/application.html.erb +34 -0
- data/app/views/layouts/commit_filter/shared/_foot.html.erb +13 -0
- data/app/views/layouts/commit_filter/shared/_head.html.erb +6 -0
- data/config/locales/en.yml +84 -0
- data/config/routes.rb +4 -0
- data/lib/commit_filter.rb +30 -1
- data/lib/commit_filter/engine.rb +9 -0
- data/lib/commit_filter/grit_extension.rb +15 -0
- data/lib/commit_filter/version.rb +1 -1
- metadata +123 -5
- data/app/views/layouts/commit_filter/application.html.erb +0 -14
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dce75b40a6b4ffd88d564ad6ca5525581035ba7f
|
4
|
+
data.tar.gz: f0f32bc638eb7e982f5ef4adf0afb743d4065113
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1a8a3f5d6d45fb3c9b320f6483f1ef582f421d90e2f0091a72dea70cf09f9391ad6db00fc82aedfb3356c23d4a0f1d7da97213c8e707a679c22c277feb7b11d2
|
7
|
+
data.tar.gz: 05333085b20f7257d60232d9edf9a38db7cd570cfb8b467e1ad8b620df84f830d2d479a95060ad710daa68cc43de254efc0f2db1a2db84e45797c953e231a698
|
Binary file
|
@@ -0,0 +1,19 @@
|
|
1
|
+
jQuery ->
|
2
|
+
$('.file_commits input').change (event) ->
|
3
|
+
event.preventDefault()
|
4
|
+
|
5
|
+
fields = {}
|
6
|
+
|
7
|
+
$.each $(this.form).serializeArray(), (index, field) ->
|
8
|
+
fields[field.name] = field.value
|
9
|
+
|
10
|
+
$.each $(this.form).find('a.diff'), (index, link) ->
|
11
|
+
url = '#'
|
12
|
+
|
13
|
+
if fields['rev'] == fields['rev_to']
|
14
|
+
alert 'Not implemented!'
|
15
|
+
else
|
16
|
+
url = "#{diffPath}?repository_path=#{fields['repository_path']}&path=#{fields['path']}&rev=#{fields['rev']}&rev_to=#{fields['rev_to']}"
|
17
|
+
|
18
|
+
$(link).attr('href', url)
|
19
|
+
$(link).text('Diff')
|
@@ -0,0 +1,15 @@
|
|
1
|
+
jQuery ->
|
2
|
+
$('#filter_repository_provider').change (event) ->
|
3
|
+
event.preventDefault()
|
4
|
+
|
5
|
+
if $(this).val() == 'plan.io'
|
6
|
+
$('#plan_io_fields').show()
|
7
|
+
else
|
8
|
+
$('#plan_io_fields').hide()
|
9
|
+
|
10
|
+
if $(this).val() == 'GitHub'
|
11
|
+
$('#github_fields').show()
|
12
|
+
$('#issue_url_field').hide()
|
13
|
+
else
|
14
|
+
$('#github_fields').hide()
|
15
|
+
$('#issue_url_field').show()
|
data/app/assets/javascripts/commit_filter/frameworks/twitter_bootstrap/3/filter_result.js.coffee
ADDED
@@ -0,0 +1,8 @@
|
|
1
|
+
jQuery ->
|
2
|
+
$(document.body).on 'click', '.commit_filter_diff_link', (event) ->
|
3
|
+
event.preventDefault()
|
4
|
+
url = $(this).attr('href')
|
5
|
+
$('.modal-title').text $(this).text()
|
6
|
+
$('.modal-body').html '<img src=\'' + spinnerImagePath + '\'/>'
|
7
|
+
$('#modal').modal('show')
|
8
|
+
$('.modal-body').load url
|
@@ -0,0 +1,65 @@
|
|
1
|
+
ul.diff {
|
2
|
+
padding:0;
|
3
|
+
}
|
4
|
+
|
5
|
+
.diff table col.lineno {
|
6
|
+
width:4em;
|
7
|
+
}
|
8
|
+
|
9
|
+
.diff h2 {
|
10
|
+
color:#333333;
|
11
|
+
font-size:14px;
|
12
|
+
letter-spacing:normal;
|
13
|
+
margin:0pt auto;
|
14
|
+
padding:0.1em 0pt 0.25em 0.5em;
|
15
|
+
}
|
16
|
+
|
17
|
+
table.diff {
|
18
|
+
font-size : 9pt;
|
19
|
+
font-family : "lucida console", "courier new", monospace;
|
20
|
+
white-space : pre;
|
21
|
+
border : 1px solid #D7D7D7;
|
22
|
+
border-collapse : collapse;
|
23
|
+
line-height : 110%;
|
24
|
+
width: 100%;
|
25
|
+
}
|
26
|
+
|
27
|
+
.diff tr {
|
28
|
+
background: white;
|
29
|
+
}
|
30
|
+
|
31
|
+
.diff td {
|
32
|
+
border : none;
|
33
|
+
padding : 0px 10px;
|
34
|
+
margin : 0px;
|
35
|
+
}
|
36
|
+
|
37
|
+
.diff td a {
|
38
|
+
text-decoration: none;
|
39
|
+
}
|
40
|
+
|
41
|
+
table.diff tr.a { background : #ddffdd; }
|
42
|
+
|
43
|
+
table.diff tr.r { background : #ffdddd; }
|
44
|
+
|
45
|
+
table.diff tr.range { background : #EAF2F5; color : #999; }
|
46
|
+
|
47
|
+
table.diff td.ln {
|
48
|
+
background : #ECECEC;
|
49
|
+
color : #aaa;
|
50
|
+
border-top:1px solid #999988;
|
51
|
+
border-bottom:1px solid #999988;
|
52
|
+
border-right:1px solid #D7D7D7;
|
53
|
+
}
|
54
|
+
|
55
|
+
.diff li {
|
56
|
+
background:#F7F7F7 none repeat scroll 0%;
|
57
|
+
border:1px solid #D7D7D7;
|
58
|
+
list-style-type:none;
|
59
|
+
margin:0pt 0pt 2em;
|
60
|
+
padding:2px;
|
61
|
+
}
|
62
|
+
|
63
|
+
table.diff .ln a {
|
64
|
+
color: #aaa;
|
65
|
+
}
|
@@ -1,4 +1,29 @@
|
|
1
1
|
module CommitFilter
|
2
2
|
class ApplicationController < ActionController::Base
|
3
|
+
helper_method :framework_views_path, :commit_filter_stylesheets, :commit_filter_javascripts, :framework_presenter
|
4
|
+
|
5
|
+
def self.framework_views_path
|
6
|
+
"commit_filter/frameworks/#{CommitFilter.configuration.frontend_framework}"
|
7
|
+
end
|
8
|
+
|
9
|
+
def framework_views_path
|
10
|
+
self.class.framework_views_path
|
11
|
+
end
|
12
|
+
|
13
|
+
def commit_filter_stylesheets
|
14
|
+
@commit_filter_stylesheets || ['application', 'commit_filter/application']
|
15
|
+
end
|
16
|
+
|
17
|
+
def commit_filter_javascripts
|
18
|
+
@commit_filter_javascripts || ['application']
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def framework_presenter
|
24
|
+
@framework_presenter ||= CommitFilter::Presenters::Frameworks::TwitterBootstrap::Version3Presenter.new(
|
25
|
+
self.view_context
|
26
|
+
)
|
27
|
+
end
|
3
28
|
end
|
4
29
|
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
class CommitFilter::Commit::DiffsController < CommitFilter::ApplicationController
|
2
|
+
def new
|
3
|
+
repository = Grit::Repo.new(params[:repository_path])
|
4
|
+
|
5
|
+
diff = repository.diff(
|
6
|
+
repository.commit(params[:rev_to]), repository.commit(params[:rev]), params[:path]
|
7
|
+
)
|
8
|
+
|
9
|
+
unless diff.length == 1
|
10
|
+
raise NotImplementedError.new(
|
11
|
+
t('commit_filter.diff.errors.diff_length_not_one', length: diff.length)
|
12
|
+
)
|
13
|
+
end
|
14
|
+
|
15
|
+
render text: DiffToHtml::GitConverter.new.get_single_file_diff_body(diff.first.diff)
|
16
|
+
rescue Exception => e
|
17
|
+
if Rails.env.development?
|
18
|
+
raise e.class.name + ': ' + e.message + ' ... ' + e.backtrace.join("\n")
|
19
|
+
else
|
20
|
+
logger.error e.class.name + ': ' + e.message + ' ... ' + e.backtrace.join("\n")
|
21
|
+
render text: t('commit_filter.general.errors.internal_server_error')
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
class CommitFilter::Commit::FiltersController < CommitFilter::ApplicationController
|
2
|
+
layout "#{CommitFilter::ApplicationController.framework_views_path}/layouts/commit_filter/application"
|
3
|
+
|
4
|
+
def new
|
5
|
+
params[:filter] ||= {}
|
6
|
+
@filter = CommitFilter::Model.new(params[:filter].merge(logger: logger))
|
7
|
+
@commit_filter_javascripts = ['application', 'commit_filter/form']
|
8
|
+
|
9
|
+
render "#{framework_views_path}/commit/filters/new"
|
10
|
+
end
|
11
|
+
|
12
|
+
def create
|
13
|
+
params[:filter] ||= {}
|
14
|
+
@filter = CommitFilter::Model.create(params[:filter].merge(logger: logger))
|
15
|
+
|
16
|
+
if @filter.valid? && @filter.last_revision.blank?
|
17
|
+
flash[:alert] = I18n.t('commit_filter.filters.create.errors.nothing_found')
|
18
|
+
end
|
19
|
+
|
20
|
+
@commit_filter_stylesheets = ['application', 'commit_filter/application', 'commit_filter/commit/diff']
|
21
|
+
@commit_filter_javascripts = [
|
22
|
+
'application', 'commit_filter/form', 'commit_filter/file_commits',
|
23
|
+
"#{CommitFilter::ApplicationController.framework_views_path}/filter_result"
|
24
|
+
]
|
25
|
+
|
26
|
+
render "#{framework_views_path}/commit/filters/new"
|
27
|
+
end
|
28
|
+
end
|
@@ -1,4 +1,59 @@
|
|
1
1
|
module CommitFilter
|
2
2
|
module ApplicationHelper
|
3
|
+
def form_field(*args, &block)
|
4
|
+
framework_presenter.form_field *args, &block
|
5
|
+
end
|
6
|
+
|
7
|
+
def path_id(path)
|
8
|
+
path.gsub(/\/|\./, '_')
|
9
|
+
end
|
10
|
+
|
11
|
+
def message_with_issue_urls(message)
|
12
|
+
if @filter.repository_provider == 'GitHub'
|
13
|
+
@filter.issue_url = "https://github.com/#{@filter.user_or_organization}/#{@filter.repository}/issues/:id"
|
14
|
+
end
|
15
|
+
|
16
|
+
if @filter.issue_url.present?
|
17
|
+
message.gsub(/#([0-9]+)/) do |s|
|
18
|
+
issue_url = @filter.issue_url.split(':id')
|
19
|
+
s = s.gsub('#', '')
|
20
|
+
issue_url = "#{issue_url[0]}#{s}#{issue_url[1]}"
|
21
|
+
"<a href=\"#{issue_url}\">##{s}</a>"
|
22
|
+
end
|
23
|
+
else
|
24
|
+
message
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def version_control_diff_link(path, rev)
|
29
|
+
rev = params['rev'] || rev
|
30
|
+
rev_to = params['rev_to'] || @filter.previous_revision_by_file[path]
|
31
|
+
|
32
|
+
url = if rev == rev_to
|
33
|
+
nil
|
34
|
+
else
|
35
|
+
"#{new_commit_diff_path}?repository_path=#{@filter.repository_path}&path=#{path}&rev=#{rev}&rev_to=#{rev_to}"
|
36
|
+
end
|
37
|
+
|
38
|
+
text = t('commit_filter.general.diff')
|
39
|
+
|
40
|
+
if url.present?
|
41
|
+
link_to text, url, class: 'diff commit_filter_diff_link'
|
42
|
+
else
|
43
|
+
text
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def annotate_file_link(text, rev, path, options = {})
|
48
|
+
url = if @filter.repository_provider == 'GitHub'
|
49
|
+
"https://github.com/#{@filter.user_or_organization}/#{@filter.repository}/blame/#{rev}/#{path}"
|
50
|
+
elsif @filter.repository_provider == 'plan.io'
|
51
|
+
"#{@filter.repository_host}/projects/#{@filter.project_slug}/repository/revisions/#{rev}/annotate/#{path}"
|
52
|
+
end
|
53
|
+
|
54
|
+
text += " (your provider is not supported)" unless url.present?
|
55
|
+
url = '#' unless url.present?
|
56
|
+
link_to text, url, target: '_blank'
|
57
|
+
end
|
3
58
|
end
|
4
59
|
end
|
@@ -0,0 +1,269 @@
|
|
1
|
+
class CommitFilter::Model
|
2
|
+
HASHTAG_REGEX = /(?:\s|^)(#(?!([0-9]?:\d+|\w+?_|_\w+?)(?:\s|$))([a-z0-9\-_]+))/i
|
3
|
+
|
4
|
+
attr_accessor :workspace, :repository, :project_slug, :branch, :path, :author, :from, :to, :id, :hashtag
|
5
|
+
attr_accessor :message, :story, :tasks, :hide_merge_commits, :logger, :issue_url, :repository_provider, :user_or_organization
|
6
|
+
attr_accessor :repository_host, :group_by_rails_file_category
|
7
|
+
attr_reader :errors, :commits_count, :last_revision, :first_revision, :previous_revision, :previous_revision_by_file
|
8
|
+
|
9
|
+
def self.create(attributes = {})
|
10
|
+
resource = new(attributes)
|
11
|
+
|
12
|
+
if resource.valid?
|
13
|
+
begin
|
14
|
+
resource.commits_by_file
|
15
|
+
rescue Grit::Git::GitTimeout
|
16
|
+
@errors ||= {}
|
17
|
+
@errors['base'] = I18n.t('commit_filter.filters.create.errors.too_many_git_timeouts')
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
resource
|
22
|
+
end
|
23
|
+
|
24
|
+
def initialize(attributes = {})
|
25
|
+
@commits_count, @previous_revision_by_file = 0, {}
|
26
|
+
|
27
|
+
initialize_attributes(attributes)
|
28
|
+
|
29
|
+
self
|
30
|
+
end
|
31
|
+
|
32
|
+
def repository_path; self.workspace.to_s + '/' + self.repository.to_s; end
|
33
|
+
|
34
|
+
def valid?
|
35
|
+
@valid = _valid? ? true : false
|
36
|
+
end
|
37
|
+
|
38
|
+
def commits_by_file
|
39
|
+
return {} unless valid?
|
40
|
+
|
41
|
+
return @files if @files
|
42
|
+
|
43
|
+
if group_by_rails_file_category
|
44
|
+
@files = {
|
45
|
+
library: { paths: [/^lib\//, /^app\/mailers\//] },
|
46
|
+
model: { paths: [/^app\/models\//, /^db\//] },
|
47
|
+
controller: { paths: [/^app\/controllers\//] },
|
48
|
+
javascript: { paths: [/^app\/assets\/javascripts\//] },
|
49
|
+
view: {
|
50
|
+
paths: [
|
51
|
+
/^app\/assets\/stylesheets\//, /^app\/views\//, /^app\/helpers\//, /^app\/presenters\//,
|
52
|
+
/^public\//
|
53
|
+
]
|
54
|
+
},
|
55
|
+
tests: { paths: [/^spec\//, /^features\//] },
|
56
|
+
configuration: { paths: [/^config\//] },
|
57
|
+
misc: { paths: [] }
|
58
|
+
}
|
59
|
+
else
|
60
|
+
@files = {}
|
61
|
+
end
|
62
|
+
|
63
|
+
catch(:done) do
|
64
|
+
commits do |page|
|
65
|
+
page.each do |commit|
|
66
|
+
add_commit_to_files(commit) if commit_attributes_match_criteria?(commit)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
if group_by_rails_file_category
|
72
|
+
@files.each {|category, setting| @files.delete(category) unless setting[:files].try(:any?) }
|
73
|
+
end
|
74
|
+
|
75
|
+
@files
|
76
|
+
rescue Grit::NoSuchPathError
|
77
|
+
@errors ||= {}
|
78
|
+
@errors['base'] = I18n.t('commit_filter.filters.create.errors.repository_not_found')
|
79
|
+
end
|
80
|
+
|
81
|
+
def files_count; @previous_revision_by_file.keys.length; end
|
82
|
+
|
83
|
+
private
|
84
|
+
|
85
|
+
def initialize_attributes(attributes)
|
86
|
+
default_attributes = {
|
87
|
+
'workspace' => CommitFilter.configuration.workspace,
|
88
|
+
'repository' => CommitFilter.configuration.repository,
|
89
|
+
'repository_provider' => CommitFilter.configuration.repository_provider,
|
90
|
+
'user_or_organization' => CommitFilter.configuration.user_or_organization,
|
91
|
+
'repository_host' => CommitFilter.configuration.repository_host,
|
92
|
+
'project_slug' => CommitFilter.configuration.project_slug,
|
93
|
+
'branch' => CommitFilter.configuration.branch,
|
94
|
+
'issue_url' => CommitFilter.configuration.issue_url,
|
95
|
+
'hide_merge_commits' => CommitFilter.configuration.hide_merge_commits
|
96
|
+
}
|
97
|
+
|
98
|
+
if CommitFilter.configuration.workspace_and_repository_from_rails_root
|
99
|
+
workspace = Rails.root.to_s.split('/')
|
100
|
+
default_attributes['repository'] = workspace.pop
|
101
|
+
default_attributes['workspace'] = workspace.join('/')
|
102
|
+
end
|
103
|
+
|
104
|
+
attributes = default_attributes.merge(attributes)
|
105
|
+
attributes['hide_merge_commits'] = false if attributes['hide_merge_commits'].to_s == '0'
|
106
|
+
attributes['to'] = 1.day.since.strftime('%Y-%m-%d') if attributes['from'].present? && attributes['to'].blank?
|
107
|
+
|
108
|
+
attributes.each {|attribute, value| self.send("#{attribute}=", value) }
|
109
|
+
end
|
110
|
+
|
111
|
+
def _valid?
|
112
|
+
@errors ||= {}
|
113
|
+
|
114
|
+
['workspace', 'repository', 'branch'].each do |field|
|
115
|
+
@errors[field] = I18n.t('commit_filter.filters.create.errors.cannot_be_blank') if self.send(field).blank?
|
116
|
+
end
|
117
|
+
|
118
|
+
if repository_provider == 'GitHub'
|
119
|
+
@errors['user_or_organization'] = I18n.t('commit_filter.filters.create.errors.cannot_be_blank') if user_or_organization.blank?
|
120
|
+
elsif repository_provider == 'plan.io'
|
121
|
+
['repository_host', 'project_slug'].each do |field|
|
122
|
+
@errors[field] = I18n.t('commit_filter.filters.create.errors.cannot_be_blank') if self.send(field).blank?
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
if path.blank? && author.blank? && id.blank? && hashtag.blank? && message.blank? && story.blank? && tasks.blank? && from.blank? && to.blank?
|
127
|
+
@errors['base'] = I18n.t('commit_filter.filters.create.errors.not_enough_criteria')
|
128
|
+
end
|
129
|
+
|
130
|
+
@errors.empty?
|
131
|
+
end
|
132
|
+
|
133
|
+
def repository_instance
|
134
|
+
@repository_instance ||= Grit::Repo.new(self.repository_path)
|
135
|
+
end
|
136
|
+
|
137
|
+
def commits
|
138
|
+
offset = 0
|
139
|
+
|
140
|
+
if id.present?
|
141
|
+
yield repository_instance.commits(id).select{|commit| commit.id == id }
|
142
|
+
else
|
143
|
+
while (page = try_two_times("Get commits from #{offset} to #{(offset + 100)}") { repository_instance.commits(self.branch, 100, offset) }).length > 0
|
144
|
+
|
145
|
+
yield page
|
146
|
+
|
147
|
+
offset += 100
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
def commit_attributes_match_criteria?(commit)
|
153
|
+
if hide_merge_commits && commit.message.match(/^Merge branch /)
|
154
|
+
false
|
155
|
+
elsif (
|
156
|
+
(message != '' && commit.message.match(message)) ||
|
157
|
+
commit_message_includes_hashtag(commit.message)
|
158
|
+
) && (author.blank? || commit.author.name == author) && between_timespan?(commit.committed_date)
|
159
|
+
true
|
160
|
+
else
|
161
|
+
@previous_revision ||= commit.id
|
162
|
+
|
163
|
+
throw :done if from.present? && Time.parse(from) > commit.committed_date
|
164
|
+
|
165
|
+
false
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
def commit_message_includes_hashtag(commit_message)
|
170
|
+
hashtag.present? && commit_message.scan(HASHTAG_REGEX).map(&:first).include?(hashtag)
|
171
|
+
end
|
172
|
+
|
173
|
+
def add_commit_to_files(commit)
|
174
|
+
@previous_revision = nil
|
175
|
+
|
176
|
+
return if hide_merge_commits && commit.message.match(/^Merge branch /)
|
177
|
+
|
178
|
+
if commit.message.match(message) && (author.blank? || commit.author.name == author) && between_timespan?(commit.committed_date)
|
179
|
+
@previous_revision = nil
|
180
|
+
else
|
181
|
+
@previous_revision ||= commit.id
|
182
|
+
|
183
|
+
throw :done if from.present? && Time.parse(from) > commit.committed_date
|
184
|
+
|
185
|
+
return
|
186
|
+
end
|
187
|
+
|
188
|
+
files = try_two_times("Commit(id: #{commit.id})#stats") { commit.stats }.files.map(&:first).select do |file_path|
|
189
|
+
path.blank? || file_path.match(path)
|
190
|
+
end
|
191
|
+
|
192
|
+
return if files.none?
|
193
|
+
|
194
|
+
@first_revision = commit.id
|
195
|
+
@last_revision ||= commit.id
|
196
|
+
@commits_count += 1
|
197
|
+
|
198
|
+
files.each {|file_path| add_commit_to_file(file_path, commit) }
|
199
|
+
end
|
200
|
+
|
201
|
+
def between_timespan?(timestamp)
|
202
|
+
return true if from.blank? && to.blank?
|
203
|
+
|
204
|
+
from_valid = from.present? && Time.parse(from) <= timestamp
|
205
|
+
to_valid = to.present? && Time.parse(to) >= timestamp
|
206
|
+
|
207
|
+
valid = if from.present? && to.present? && from_valid && to_valid
|
208
|
+
true
|
209
|
+
elsif (from.blank? || to.blank?) && ((from.present? && from_valid) || (to.present? && to_valid))
|
210
|
+
true
|
211
|
+
else
|
212
|
+
false
|
213
|
+
end
|
214
|
+
|
215
|
+
valid
|
216
|
+
end
|
217
|
+
|
218
|
+
def add_commit_to_file(file_path, commit)
|
219
|
+
category = nil
|
220
|
+
|
221
|
+
if group_by_rails_file_category
|
222
|
+
category = :misc
|
223
|
+
|
224
|
+
if file_path.match(/\//)
|
225
|
+
@files.each do |current_category, setting|
|
226
|
+
if setting[:paths].select{|part| file_path.match(part) }.any?
|
227
|
+
category = current_category; break
|
228
|
+
end
|
229
|
+
end
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
if commit.parents.any?
|
234
|
+
@previous_revision_by_file[file_path] = commit.parents.first.id
|
235
|
+
else
|
236
|
+
# e.g. first commit has no parents
|
237
|
+
@previous_revision_by_file[file_path] = nil
|
238
|
+
end
|
239
|
+
|
240
|
+
@files[category][:files] ||= {} if category.present?
|
241
|
+
|
242
|
+
files = category.present? ? @files[category][:files] : @files
|
243
|
+
|
244
|
+
files[file_path] ||= []
|
245
|
+
files[file_path] << {
|
246
|
+
id: commit.id, committed_at: commit.committed_date.strftime('%d.%m.%y %H:%M'),
|
247
|
+
message: commit.message, author: commit.author.name
|
248
|
+
}
|
249
|
+
end
|
250
|
+
|
251
|
+
# alternative for Integer#tries to log try number and sleep between
|
252
|
+
def try_two_times(message = '')
|
253
|
+
tries ||= 1
|
254
|
+
|
255
|
+
if CommitFilter.configuration.git_debug_logging
|
256
|
+
logger.info "#{Time.now.strftime('%H:%M:%S')} #{message} (try ##{tries})"
|
257
|
+
end
|
258
|
+
|
259
|
+
yield
|
260
|
+
rescue Grit::Git::GitTimeout => e
|
261
|
+
if (tries += 1) == 2
|
262
|
+
sleep 2
|
263
|
+
|
264
|
+
retry
|
265
|
+
else
|
266
|
+
raise e
|
267
|
+
end
|
268
|
+
end
|
269
|
+
end
|
data/app/presenters/commit_filter/presenters/frameworks/twitter_bootstrap/version3_presenter.rb
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
class CommitFilter::Presenters::Frameworks::TwitterBootstrap::Version3Presenter < CommitFilter::ApplicationPresenter
|
2
|
+
def flash_messages
|
3
|
+
flash_messages = []
|
4
|
+
|
5
|
+
flash.each do |type, message|
|
6
|
+
flash.delete(type)
|
7
|
+
content = content_tag(
|
8
|
+
:button,
|
9
|
+
content_tag(:span, raw('×'), 'aria-hidden' => 'true'),
|
10
|
+
class: 'close', 'data-dismiss' => 'alert', 'aria-label' => 'Close'
|
11
|
+
)
|
12
|
+
type = :success if ['notice'].include? type.to_s
|
13
|
+
type = :danger if ['alert'].include? type.to_s
|
14
|
+
content += raw(message)
|
15
|
+
text = content_tag(:div, content, class: "alert fade in alert-#{type}")
|
16
|
+
flash_messages << text if message
|
17
|
+
end
|
18
|
+
|
19
|
+
flash_messages.join('\n').html_safe
|
20
|
+
end
|
21
|
+
|
22
|
+
def form_field(filter, name, options = {})
|
23
|
+
options[:placeholder] = t("commit_filter.filters.form.fields.#{name}.placeholder", default: 'NULL')
|
24
|
+
options.delete :placeholder if options[:placeholder] == 'NULL'
|
25
|
+
hint = t("commit_filter.filters.form.fields.#{name}.hint", default: 'NULL')
|
26
|
+
hint = nil if hint == 'NULL'
|
27
|
+
error = (filter.errors || {})[name]
|
28
|
+
field = options.delete(:field)
|
29
|
+
|
30
|
+
content_tag :div, class: 'form-group' + (error ? ' has-error' : '') do
|
31
|
+
content = []
|
32
|
+
content << label_tag("filter[#{name}]", t("commit_filter.filters.form.fields.#{name}.title"), class: 'col-sm-3 control-label')
|
33
|
+
|
34
|
+
content << content_tag(:div, class: 'col-sm-8') do
|
35
|
+
controls = []
|
36
|
+
|
37
|
+
if field.present?
|
38
|
+
controls << field
|
39
|
+
else
|
40
|
+
controls << text_field_tag("filter[#{name}]", filter.send(name), { class: 'form-control' }.merge(options))
|
41
|
+
end
|
42
|
+
|
43
|
+
controls << content_tag(:p, hint, class: 'help-block') if hint
|
44
|
+
controls << content_tag(:span, error, class: 'help-inline') if error
|
45
|
+
raw controls.join(' ')
|
46
|
+
end
|
47
|
+
|
48
|
+
raw content.join(' ')
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
data/app/views/commit_filter/frameworks/twitter_bootstrap/3/commit/filters/_categories.html.erb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
<div class="panel-group" id="commit_filter_accordion" role="tablist" aria-multiselectable="true">
|
2
|
+
<div class="panel panel-default">
|
3
|
+
<% index = 0 %>
|
4
|
+
<% @filter.commits_by_file.each do |category, setting| %>
|
5
|
+
<div class="panel-heading" role="tab" id="heading<%= index + 1 %>">
|
6
|
+
<h4 class="panel-title">
|
7
|
+
<a
|
8
|
+
data-toggle="collapse" data-parent="#commit_filter_accordion"
|
9
|
+
href="#commit_category_<%= category %>" aria-expanded="true"
|
10
|
+
aria-controls="commit_category_<%= category %>"
|
11
|
+
>
|
12
|
+
<%= category %> (<%= setting[:files].keys.length %> <%= t('commit_filter.general.files') %>)
|
13
|
+
</a>
|
14
|
+
</h4>
|
15
|
+
</div>
|
16
|
+
|
17
|
+
<div
|
18
|
+
id="commit_category_<%= category %>" class="panel-collapse collapse<% if index == 0 %> in<% end %>"
|
19
|
+
role="tabpanel" aria-labelledby="heading<%= index + 1 %>"
|
20
|
+
>
|
21
|
+
<div class="panel-body" style="padding:15px 15px 0px 15px;">
|
22
|
+
<%= render partial: "#{framework_views_path}/commit/filters/files", locals: { commits_by_file: setting[:files], paths: setting[:paths] } %>
|
23
|
+
</div>
|
24
|
+
</div>
|
25
|
+
<% index += 1 %>
|
26
|
+
<% end %>
|
27
|
+
</div>
|
28
|
+
</div>
|
data/app/views/commit_filter/frameworks/twitter_bootstrap/3/commit/filters/_file_commits.html.erb
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
<% previous_file_rev = @filter.previous_revision_by_file[path] %>
|
2
|
+
<p>
|
3
|
+
<strong><%= t('commit_filter.filters.form.fields.path.title') %>:</strong> <%= path %>
|
4
|
+
</p>
|
5
|
+
<%= form_tag '#', method: 'post', class: 'file_commits' do %>
|
6
|
+
<%= hidden_field_tag :repository_path, @filter.repository_path %>
|
7
|
+
<%= hidden_field_tag :project_slug, @filter.project_slug %>
|
8
|
+
<%= hidden_field_tag :path, path %>
|
9
|
+
<table class='table table-striped table-condensed'>
|
10
|
+
<thead>
|
11
|
+
<tr>
|
12
|
+
<th colspan="2" style="width: 50px; text-align:center">
|
13
|
+
<%= version_control_diff_link path, commits.first[:id].try(:to_s) %>
|
14
|
+
</th>
|
15
|
+
<th style="width:150px;"><%= t('commit_filter.general.date') %></th>
|
16
|
+
<th style="width:150px;"><%= t('commit_filter.filters.form.fields.author.title') %></th>
|
17
|
+
<th><%= t('commit_filter.filters.form.fields.message.title') %></th>
|
18
|
+
</tr>
|
19
|
+
</thead>
|
20
|
+
<tbody>
|
21
|
+
<% param = params[path_id(path)] || {} %>
|
22
|
+
<% commits.each_with_index do |commit, commits_index| %>
|
23
|
+
<tr>
|
24
|
+
<td style="width:25px; text-align:center">
|
25
|
+
<% first_commit = previous_file_rev.blank? && commit[:id].try(:to_s) == commits.last[:id].try(:to_s) %>
|
26
|
+
<% unless first_commit %>
|
27
|
+
<% checked = param['rev'] == commit[:id].try(:to_s) ? true : false %>
|
28
|
+
<% checked = true if commits_index == 0 && !param.has_key?('rev') %>
|
29
|
+
<%= radio_button_tag :rev, commit[:id].try(:to_s), checked, id: '' %>
|
30
|
+
<% end %>
|
31
|
+
</td>
|
32
|
+
<td style="width:25px; text-align:center">
|
33
|
+
<% unless commits_index == 0 %>
|
34
|
+
<% checked = param['rev_to'] == commit[:id].try(:to_s) ? true : false %>
|
35
|
+
<% checked = true if commits_index == (commits.length - 1) && !param.has_key?('rev_to') %>
|
36
|
+
<%= radio_button_tag :rev_to, commit[:id].try(:to_s), checked, id: '' %>
|
37
|
+
<% end %>
|
38
|
+
</td>
|
39
|
+
<td style="width:150px;"><%= annotate_file_link commit[:committed_at], commit[:id], path %></td>
|
40
|
+
<td style="width:150px;"><%= commit[:author]%></td>
|
41
|
+
<td>
|
42
|
+
<%= raw message_with_issue_urls(commit[:message]) %>
|
43
|
+
</td>
|
44
|
+
</tr>
|
45
|
+
<% end %>
|
46
|
+
</tbody>
|
47
|
+
<tfoot>
|
48
|
+
<% if previous_file_rev.present? %>
|
49
|
+
<tr>
|
50
|
+
<td>
|
51
|
+
</td>
|
52
|
+
<td style="width:25px; text-align:center">
|
53
|
+
<% checked = param['rev_to'] == previous_file_rev ? true : false %>
|
54
|
+
<% checked = true unless param.has_key?('rev_to') %>
|
55
|
+
<%= radio_button_tag :rev_to, previous_file_rev, checked, id: '' %>
|
56
|
+
</td>
|
57
|
+
<th colspan="3"/>
|
58
|
+
</tr>
|
59
|
+
<% end %>
|
60
|
+
<tr>
|
61
|
+
<th colspan="2" style="text-align:center">
|
62
|
+
<%= version_control_diff_link path, commits.first[:id].try(:to_s) %>
|
63
|
+
</th>
|
64
|
+
<th colspan="3"/>
|
65
|
+
</tr>
|
66
|
+
</tfoot>
|
67
|
+
</table>
|
68
|
+
<% end %>
|
@@ -0,0 +1,26 @@
|
|
1
|
+
<% paths ||= nil %>
|
2
|
+
|
3
|
+
<div role="tabpanel">
|
4
|
+
<ul class="nav nav-tabs" role="tablist">
|
5
|
+
<% file_index = 0 %>
|
6
|
+
<% commits_by_file.keys.sort_by{ |x| x.downcase }.each do |path| %>
|
7
|
+
<% matching_part = paths.nil? ? nil : paths.select{|part| path.match(part) }.first %>
|
8
|
+
<li role="presentation"<% if file_index == 0 %> class="active"<% end %>>
|
9
|
+
<a href="#commit_file_<%= path.gsub(/\/|\./, '_') %>" aria-controls="commit_file_<%= path.gsub(/\/|\./, '_') %>" role="tab" data-toggle="tab">
|
10
|
+
<%= matching_part ? path.gsub(matching_part, '') : path %>
|
11
|
+
</a>
|
12
|
+
</li>
|
13
|
+
<% file_index += 1 %>
|
14
|
+
<% end %>
|
15
|
+
</ul>
|
16
|
+
<div class="tab-content">
|
17
|
+
<% file_index = 0 %>
|
18
|
+
<% commits_by_file.keys.sort_by{ |x| x.downcase }.each do |path| %>
|
19
|
+
<% commits = commits_by_file[path] %>
|
20
|
+
<div role="tabpanel" class="tab-pane<% if file_index == 0 %> active<% end %>" id="commit_file_<%= path.gsub(/\/|\./, '_') %>">
|
21
|
+
<%= render "#{framework_views_path}/commit/filters/file_commits", commits: commits, path: path %>
|
22
|
+
</div>
|
23
|
+
<% file_index += 1 %>
|
24
|
+
<% end %>
|
25
|
+
</div>
|
26
|
+
</div>
|
@@ -0,0 +1,80 @@
|
|
1
|
+
<%= form_tag commit_filter.commit_filters_path, method: 'post', class: 'form-horizontal', id: 'commit_filter_form' do %>
|
2
|
+
<% unless action_name == 'new' || @filter.valid? %>
|
3
|
+
<div class="alert fade in alert-danger">
|
4
|
+
<strong><%= t('commit_filter.filters.form.invalid') %></strong>
|
5
|
+
<ul>
|
6
|
+
<% @filter.errors.each do |field, error| %>
|
7
|
+
<li><%= field.humanize %>: <%=error %></li>
|
8
|
+
<% end %>
|
9
|
+
</ul>
|
10
|
+
</div>
|
11
|
+
<% end %>
|
12
|
+
|
13
|
+
<fieldset>
|
14
|
+
<legend>
|
15
|
+
<%= t('commit_filter.filters.form.tabs.basic.title') %>
|
16
|
+
</legend>
|
17
|
+
|
18
|
+
<%= form_field @filter, 'workspace', size: 45 %>
|
19
|
+
<%= form_field(
|
20
|
+
@filter, 'repository_provider', size: 45,
|
21
|
+
field: select_tag(
|
22
|
+
'filter[repository_provider]', options_for_select(['', 'GitHub', 'plan.io'], @filter.repository_provider),
|
23
|
+
style: 'width:325px;'
|
24
|
+
)
|
25
|
+
) %>
|
26
|
+
<div id="github_fields" style="display:<%= @filter.repository_provider == 'GitHub' ? 'block' : 'none' %>">
|
27
|
+
<%= form_field @filter, 'user_or_organization', size: 45 %>
|
28
|
+
</div>
|
29
|
+
<div id="plan_io_fields" style="display:<%= @filter.repository_provider == 'plan.io' ? 'block' : 'none' %>">
|
30
|
+
<%= form_field @filter, 'repository_host', size: 45 %>
|
31
|
+
<%= form_field @filter, 'project_slug', size: 45 %>
|
32
|
+
</div>
|
33
|
+
<%= form_field @filter, 'repository', size: 45 %>
|
34
|
+
<%= form_field @filter, 'branch', size: 45 %>
|
35
|
+
|
36
|
+
<div id="issue_url_field" style="display:<%= @filter.repository_provider == 'GitHub' ? 'none' : 'block' %>">
|
37
|
+
<%= form_field @filter, 'issue_url', size: 45 %>
|
38
|
+
</div>
|
39
|
+
|
40
|
+
<% field = capture do %>
|
41
|
+
<%= radio_button_tag 'filter[group_by_rails_file_category]', '1', @filter.group_by_rails_file_category ? true : false %>
|
42
|
+
<%= t('commit_filter.general.yes') %>
|
43
|
+
<%= radio_button_tag 'filter[group_by_rails_file_category]', '0', @filter.group_by_rails_file_category ? false : true %>
|
44
|
+
<%= t('commit_filter.general.no') %>
|
45
|
+
<% end %>
|
46
|
+
<%= form_field @filter, 'group_by_rails_file_category', size: 45, field: field %>
|
47
|
+
</fieldset>
|
48
|
+
<fieldset>
|
49
|
+
<legend><%= t('commit_filter.filters.form.tabs.time_span.title') %></legend>
|
50
|
+
|
51
|
+
<%= form_field @filter, 'from', size: 45, class: 'datepicker' %>
|
52
|
+
<%= form_field @filter, 'to', size: 45, class: 'datepicker' %>
|
53
|
+
</fieldset>
|
54
|
+
<fieldset>
|
55
|
+
<legend><%= t('commit_filter.filters.form.tabs.commit.title') %></legend>
|
56
|
+
|
57
|
+
<%= form_field @filter, 'id', size: 45 %>
|
58
|
+
<%= form_field @filter, 'hashtag', size: 45 %>
|
59
|
+
<%= form_field @filter, 'message', size: 45 %>
|
60
|
+
<%= form_field @filter, 'path', size: 45 %>
|
61
|
+
<%= form_field @filter, 'author', size: 45 %>
|
62
|
+
|
63
|
+
<% field = capture do %>
|
64
|
+
<%= radio_button_tag 'filter[hide_merge_commits]', '1', @filter.hide_merge_commits ? true : false %>
|
65
|
+
<%= t('commit_filter.general.yes') %>
|
66
|
+
<%= radio_button_tag 'filter[hide_merge_commits]', '0', @filter.hide_merge_commits ? false : true %>
|
67
|
+
<%= t('commit_filter.general.no') %>
|
68
|
+
<% end %>
|
69
|
+
<%= form_field @filter, 'hide_merge_commits', size: 45, field: field %>
|
70
|
+
</fieldset>
|
71
|
+
|
72
|
+
<p>
|
73
|
+
</p>
|
74
|
+
|
75
|
+
<div class="form-group">
|
76
|
+
<div class="col-sm-offset-3 col-sm-10">
|
77
|
+
<button type="submit" class="btn btn-primary"><%= t('commit_filter.filters.form.submit')%></button>
|
78
|
+
</div>
|
79
|
+
</div>
|
80
|
+
<% end %>
|
@@ -0,0 +1,24 @@
|
|
1
|
+
<div class="row">
|
2
|
+
<div class="col-sm-4 col-md-4">
|
3
|
+
<%= render "#{framework_views_path}/commit/filters/form" %>
|
4
|
+
</div>
|
5
|
+
<div class="col-sm-8 col-md-8">
|
6
|
+
<% if @filter.valid? && @filter.last_revision.present? %>
|
7
|
+
<p>
|
8
|
+
<strong><%= t('commit_filter.general.commits') %>:</strong> <%= @filter.commits_count %>
|
9
|
+
<strong><%= t('commit_filter.general.files') %>:</strong> <%= @filter.files_count %>
|
10
|
+
</p>
|
11
|
+
|
12
|
+
<% if @filter.group_by_rails_file_category %>
|
13
|
+
<%= render partial: "#{framework_views_path}/commit/filters/categories" %>
|
14
|
+
<% else %>
|
15
|
+
<%= render partial: "#{framework_views_path}/commit/filters/files", locals: { commits_by_file: @filter.commits_by_file } %>
|
16
|
+
<% end %>
|
17
|
+
<% end %>
|
18
|
+
</div>
|
19
|
+
</div>
|
20
|
+
|
21
|
+
<% content_for :top_javascript do %>
|
22
|
+
var repositoryProvider = "<%= @filter.repository_provider %>";
|
23
|
+
var repositoryHost = "<%= @filter.repository_host %>";
|
24
|
+
<% end %>
|
@@ -0,0 +1,34 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html lang="en">
|
3
|
+
<head>
|
4
|
+
<%= render partial: 'layouts/commit_filter/shared/head' %>
|
5
|
+
</head>
|
6
|
+
<body>
|
7
|
+
<div class="modal fade" id="modal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
|
8
|
+
<div class="modal-dialog" style="width:800px; height:500px;">
|
9
|
+
<div class="modal-content">
|
10
|
+
<div class="modal-header">
|
11
|
+
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
|
12
|
+
<h4 class="modal-title" id="myModalLabel"><%= t('general.loading') %></h4>
|
13
|
+
</div>
|
14
|
+
<div class="modal-body" style="height:400px; overflow:scroll;">
|
15
|
+
<%= image_tag 'commit_filter/spinner.gif' %>
|
16
|
+
</div>
|
17
|
+
<div class="modal-footer">
|
18
|
+
<button type="button" class="btn btn-default" data-dismiss="modal"><%= t('general.close') %></button>
|
19
|
+
</div>
|
20
|
+
</div>
|
21
|
+
</div>
|
22
|
+
</div>
|
23
|
+
|
24
|
+
<div class="container-fluid">
|
25
|
+
<div id="flash">
|
26
|
+
<%= framework_presenter.flash_messages %>
|
27
|
+
</div>
|
28
|
+
|
29
|
+
<%= yield %>
|
30
|
+
</div>
|
31
|
+
|
32
|
+
<%= render partial: 'layouts/commit_filter/shared/foot' %>
|
33
|
+
</body>
|
34
|
+
</html>
|
@@ -0,0 +1,13 @@
|
|
1
|
+
<%= javascript_include_tag *commit_filter_javascripts %>
|
2
|
+
<%= yield :javascript_includes %>
|
3
|
+
|
4
|
+
<%= javascript_tag do %>
|
5
|
+
var diffPath = "<%= new_commit_diff_path %>";
|
6
|
+
var spinnerImagePath = "<%= asset_path('home_page/spinner.gif') %>";
|
7
|
+
|
8
|
+
<%= yield :top_javascript %>
|
9
|
+
|
10
|
+
$(function() {
|
11
|
+
<%= yield(:document_ready) %>
|
12
|
+
});
|
13
|
+
<% end %>
|
@@ -0,0 +1,6 @@
|
|
1
|
+
<meta charset="utf-8">
|
2
|
+
<meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1">
|
3
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
4
|
+
<title><%= t('commit_filter.general.title') %></title>
|
5
|
+
<%= stylesheet_link_tag *commit_filter_stylesheets, media: 'all' %>
|
6
|
+
<%= csrf_meta_tags %>
|
@@ -0,0 +1,84 @@
|
|
1
|
+
en:
|
2
|
+
commit_filter:
|
3
|
+
general:
|
4
|
+
title: Commit Filter
|
5
|
+
commits: Commits
|
6
|
+
files: Files
|
7
|
+
yes: Yes
|
8
|
+
no: No
|
9
|
+
date: Date
|
10
|
+
loading: Loading
|
11
|
+
diff: Diff
|
12
|
+
close: Close
|
13
|
+
errors:
|
14
|
+
internal_server_error: Internal server error.
|
15
|
+
|
16
|
+
filters:
|
17
|
+
form:
|
18
|
+
invalid: Filter is invalid!
|
19
|
+
|
20
|
+
tabs:
|
21
|
+
basic:
|
22
|
+
title: Basic
|
23
|
+
time_span:
|
24
|
+
title: Time Span
|
25
|
+
commit:
|
26
|
+
title: Commit
|
27
|
+
|
28
|
+
fields:
|
29
|
+
workspace:
|
30
|
+
title: Workspace
|
31
|
+
placeholder: e.g. /users/user_name/workspace
|
32
|
+
repository:
|
33
|
+
title: Repository
|
34
|
+
repository_provider:
|
35
|
+
title: Repository Provider
|
36
|
+
user_or_organization:
|
37
|
+
title: User or Organization
|
38
|
+
repository_host:
|
39
|
+
title: Repository Host
|
40
|
+
project_slug:
|
41
|
+
title: Project slug
|
42
|
+
branch:
|
43
|
+
title: Branch
|
44
|
+
issue_url:
|
45
|
+
title: Issue URL
|
46
|
+
placeholder: e.g. https://host/repository_path/issues/:id
|
47
|
+
group_by_rails_file_category:
|
48
|
+
title: Group by File Category
|
49
|
+
hint: Only for Rails apps.
|
50
|
+
path:
|
51
|
+
title: Path
|
52
|
+
author:
|
53
|
+
title: Author
|
54
|
+
from:
|
55
|
+
title: From
|
56
|
+
placeholder: e.g. 2015-01-01
|
57
|
+
to:
|
58
|
+
title: To
|
59
|
+
placeholder: e.g. 2015-01-01
|
60
|
+
id:
|
61
|
+
title: ID
|
62
|
+
hashtag:
|
63
|
+
title: Hashtag
|
64
|
+
hint: Including "#".
|
65
|
+
message:
|
66
|
+
title: Message
|
67
|
+
hide_merge_commits:
|
68
|
+
title: Hide merge commits
|
69
|
+
hint: Message matches "^Merge branch "
|
70
|
+
|
71
|
+
submit: Submit
|
72
|
+
|
73
|
+
create:
|
74
|
+
diff_from_last_to_previous_revision: Diff from last to previous revision (currently includes commits not matching the current filter)
|
75
|
+
|
76
|
+
errors:
|
77
|
+
nothing_found: Nothing found.
|
78
|
+
repository_not_found: Repository not found.
|
79
|
+
cannot_be_blank: can't be blank.
|
80
|
+
not_enough_criteria: "Please set at least one of these: path, author, id, hashtag, message, story, tasks, from, to."
|
81
|
+
too_many_git_timeouts: Too many timeouts for git connection!
|
82
|
+
diff:
|
83
|
+
errors:
|
84
|
+
diff_length_not_one: "Not implemented error: diff length is not 1 but %{diff.length}."
|
data/config/routes.rb
CHANGED
data/lib/commit_filter.rb
CHANGED
@@ -1,4 +1,33 @@
|
|
1
|
-
|
1
|
+
# misc
|
2
|
+
require 'gem_config'
|
3
|
+
require 'grit'
|
4
|
+
|
5
|
+
# view
|
6
|
+
require 'jquery-rails'
|
7
|
+
require 'coffee_script'
|
8
|
+
require 'diff_to_html'
|
9
|
+
require 'pygments'
|
10
|
+
|
11
|
+
require 'commit_filter/grit_extension'
|
12
|
+
|
13
|
+
require 'commit_filter/engine'
|
2
14
|
|
3
15
|
module CommitFilter
|
16
|
+
include GemConfig::Base
|
17
|
+
|
18
|
+
with_configuration do
|
19
|
+
has :frontend_framework, classes: String, values: ['twitter_bootstrap/3'], default: 'twitter_bootstrap/3'
|
20
|
+
has :workspace_and_repository_from_rails_root, classes: [TrueClass, FalseClass], default: true
|
21
|
+
has :workspace, classes: String
|
22
|
+
has :repository, classes: String
|
23
|
+
has :repository_provider, classes: String
|
24
|
+
has :user_or_organization, classes: String
|
25
|
+
has :repository_host, classes: String
|
26
|
+
has :project_slug, classes: String
|
27
|
+
has :branch, classes: String, default: 'master'
|
28
|
+
has :issue_url, classes: String
|
29
|
+
has :group_by_rails_file_category, classes: [TrueClass, FalseClass], default: false
|
30
|
+
has :hide_merge_commits, classes: [TrueClass, FalseClass], default: true
|
31
|
+
has :git_debug_logging, classes: [TrueClass, FalseClass], default: false
|
32
|
+
end
|
4
33
|
end
|
data/lib/commit_filter/engine.rb
CHANGED
@@ -1,5 +1,14 @@
|
|
1
1
|
module CommitFilter
|
2
2
|
class Engine < ::Rails::Engine
|
3
3
|
isolate_namespace CommitFilter
|
4
|
+
|
5
|
+
config.to_prepare do
|
6
|
+
Rails.application.config.assets.precompile += %w(
|
7
|
+
commit_filter/commit/diff.css
|
8
|
+
commit_filter/form.js
|
9
|
+
commit_filter/file_commits.js
|
10
|
+
commit_filter/frameworks/twitter_bootstrap/3/filter_result.js
|
11
|
+
)
|
12
|
+
end
|
4
13
|
end
|
5
14
|
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Grit
|
2
|
+
class Repo
|
3
|
+
def diff(a, b, *paths)
|
4
|
+
diff = self.git.native('diff', { 'no-ext-diff' => true }, a, b, '--', *paths)
|
5
|
+
|
6
|
+
if diff =~ /diff --git a/
|
7
|
+
diff = diff.sub(/.*?(diff --git a)/m, '\1')
|
8
|
+
else
|
9
|
+
diff = ''
|
10
|
+
end
|
11
|
+
|
12
|
+
Diff.list_from_string(self, diff)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: commit_filter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mathias Gawlista
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-03-
|
11
|
+
date: 2015-03-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -24,8 +24,105 @@ dependencies:
|
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: 4.2.0
|
27
|
-
|
28
|
-
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: gem_config
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 0.3.1
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 0.3.1
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: sqlite3
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 1.3.10
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 1.3.10
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: gitlab-grit
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 2.7.3
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 2.7.3
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: coffee-script
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 2.3.0
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 2.3.0
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: jquery-rails
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: 4.0.3
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: 4.0.3
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: diff_to_html
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: 0.0.1
|
104
|
+
type: :runtime
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: 0.0.1
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: pygments.rb
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - "~>"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: 0.6.2
|
118
|
+
type: :runtime
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - "~>"
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: 0.6.2
|
125
|
+
description: "& grouping by category + file http://bit.ly/commit-filter-0-1-0"
|
29
126
|
email:
|
30
127
|
- gawlista@gmail.com
|
31
128
|
executables: []
|
@@ -35,13 +132,34 @@ files:
|
|
35
132
|
- MIT-LICENSE
|
36
133
|
- README.md
|
37
134
|
- Rakefile
|
135
|
+
- app/assets/images/commit_filter/spinner.gif
|
136
|
+
- app/assets/javascripts/commit_filter/file_commits.js.coffee
|
137
|
+
- app/assets/javascripts/commit_filter/form.js.coffee
|
138
|
+
- app/assets/javascripts/commit_filter/frameworks/twitter_bootstrap/3/filter_result.js.coffee
|
38
139
|
- app/assets/stylesheets/commit_filter/application.css
|
140
|
+
- app/assets/stylesheets/commit_filter/base.css
|
141
|
+
- app/assets/stylesheets/commit_filter/commit/diff.css
|
39
142
|
- app/controllers/commit_filter/application_controller.rb
|
143
|
+
- app/controllers/commit_filter/commit/diffs_controller.rb
|
144
|
+
- app/controllers/commit_filter/commit/filters_controller.rb
|
40
145
|
- app/helpers/commit_filter/application_helper.rb
|
41
|
-
- app/
|
146
|
+
- app/models/commit_filter/model.rb
|
147
|
+
- app/presenters/commit_filter/application_presenter.rb
|
148
|
+
- app/presenters/commit_filter/presenter.rb
|
149
|
+
- app/presenters/commit_filter/presenters/frameworks/twitter_bootstrap/version3_presenter.rb
|
150
|
+
- app/views/commit_filter/frameworks/twitter_bootstrap/3/commit/filters/_categories.html.erb
|
151
|
+
- app/views/commit_filter/frameworks/twitter_bootstrap/3/commit/filters/_file_commits.html.erb
|
152
|
+
- app/views/commit_filter/frameworks/twitter_bootstrap/3/commit/filters/_files.html.erb
|
153
|
+
- app/views/commit_filter/frameworks/twitter_bootstrap/3/commit/filters/_form.html.erb
|
154
|
+
- app/views/commit_filter/frameworks/twitter_bootstrap/3/commit/filters/new.html.erb
|
155
|
+
- app/views/commit_filter/frameworks/twitter_bootstrap/3/layouts/commit_filter/application.html.erb
|
156
|
+
- app/views/layouts/commit_filter/shared/_foot.html.erb
|
157
|
+
- app/views/layouts/commit_filter/shared/_head.html.erb
|
158
|
+
- config/locales/en.yml
|
42
159
|
- config/routes.rb
|
43
160
|
- lib/commit_filter.rb
|
44
161
|
- lib/commit_filter/engine.rb
|
162
|
+
- lib/commit_filter/grit_extension.rb
|
45
163
|
- lib/commit_filter/version.rb
|
46
164
|
- lib/tasks/commit_filter_tasks.rake
|
47
165
|
homepage: http://GitHub.com/volontarian/commit_filter
|
@@ -1,14 +0,0 @@
|
|
1
|
-
<!DOCTYPE html>
|
2
|
-
<html>
|
3
|
-
<head>
|
4
|
-
<title>CommitFilter</title>
|
5
|
-
<%= stylesheet_link_tag "commit_filter/application", media: "all" %>
|
6
|
-
<%= javascript_include_tag "commit_filter/application" %>
|
7
|
-
<%= csrf_meta_tags %>
|
8
|
-
</head>
|
9
|
-
<body>
|
10
|
-
|
11
|
-
<%= yield %>
|
12
|
-
|
13
|
-
</body>
|
14
|
-
</html>
|