redmine_git_hosting_v0.7.9_redmine_scm_compatibility_patch.diff
app/controllers/repository_protected_branches_controller.rb | ||
---|---|---|
1 |
class RepositoryProtectedBranchesController < RedmineGitHostingController |
|
2 |
unloadable |
|
3 | ||
4 |
before_filter :set_current_tab |
|
5 |
before_filter :can_view_protected_branches, :only => [:index] |
|
6 |
before_filter :can_create_protected_branches, :only => [:new, :create] |
|
7 |
before_filter :can_edit_protected_branches, :only => [:edit, :update, :destroy] |
|
8 | ||
9 |
before_filter :find_repository_protected_branch, :except => [:index, :new, :create, :sort] |
|
10 | ||
11 | ||
12 |
def index |
|
13 |
@repository_protected_branches = RepositoryProtectedBranche.find_all_by_repository_id(@repository.id) |
|
14 | ||
15 |
respond_to do |format| |
|
16 |
format.html { render :layout => 'popup' } |
|
17 |
format.js |
|
18 |
end |
|
19 |
end |
|
20 | ||
21 | ||
22 |
def new |
|
23 |
@protected_branch = RepositoryProtectedBranche.new() |
|
24 |
@protected_branch.repository = @repository |
|
25 |
@protected_branch.user_list = [] |
|
26 |
end |
|
27 | ||
28 | ||
29 |
def create |
|
30 |
@protected_branch = RepositoryProtectedBranche.new(params[:repository_protected_branche]) |
|
31 |
@protected_branch.repository = @repository |
|
32 | ||
33 |
respond_to do |format| |
|
34 |
if @protected_branch.save |
|
35 |
flash[:notice] = l(:notice_protected_branch_created) |
|
36 | ||
37 |
format.html { redirect_to success_url } |
|
38 |
format.js { render :js => "window.location = #{success_url.to_json};" } |
|
39 |
else |
|
40 |
format.html { |
|
41 |
flash[:error] = l(:notice_protected_branch_create_failed) |
|
42 |
render :action => "create" |
|
43 |
} |
|
44 |
format.js { render "form_error", :layout => false } |
|
45 |
end |
|
46 |
end |
|
47 |
end |
|
48 | ||
49 | ||
50 |
def update |
|
51 |
respond_to do |format| |
|
52 |
if @protected_branch.update_attributes(params[:repository_protected_branche]) |
|
53 |
flash[:notice] = l(:notice_protected_branch_updated) |
|
54 | ||
55 |
format.html { redirect_to success_url } |
|
56 |
format.js { render :js => "window.location = #{success_url.to_json};" } |
|
57 |
else |
|
58 |
format.html { |
|
59 |
flash[:error] = l(:notice_protected_branch_update_failed) |
|
60 |
render :action => "edit" |
|
61 |
} |
|
62 |
format.js { render "form_error", :layout => false } |
|
63 |
end |
|
64 |
end |
|
65 |
end |
|
66 | ||
67 | ||
68 |
def destroy |
|
69 |
respond_to do |format| |
|
70 |
if @protected_branch.destroy |
|
71 |
flash[:notice] = l(:notice_protected_branch_deleted) |
|
72 |
format.js { render :js => "window.location = #{success_url.to_json};" } |
|
73 |
else |
|
74 |
format.js { render :layout => false } |
|
75 |
end |
|
76 |
end |
|
77 |
end |
|
78 | ||
79 | ||
80 |
def clone |
|
81 |
@protected_branch = RepositoryProtectedBranche.clone_from(params[:id]) |
|
82 |
render "new" |
|
83 |
end |
|
84 | ||
85 | ||
86 |
def sort |
|
87 |
params[:repository_protected_branche].each_with_index do |id, index| |
|
88 |
RepositoryProtectedBranche.update_all({position: index + 1}, {id: id}) |
|
89 |
end |
|
90 |
render :nothing => true |
|
91 |
end |
|
92 | ||
93 | ||
94 |
private |
|
95 | ||
96 | ||
97 |
def can_view_protected_branches |
|
98 |
render_403 unless view_context.user_allowed_to(:view_repository_protected_branches, @project) |
|
99 |
end |
|
100 | ||
101 | ||
102 |
def can_create_protected_branches |
|
103 |
render_403 unless view_context.user_allowed_to(:create_repository_protected_branches, @project) |
|
104 |
end |
|
105 | ||
106 | ||
107 |
def can_edit_protected_branches |
|
108 |
render_403 unless view_context.user_allowed_to(:edit_repository_protected_branches, @project) |
|
109 |
end |
|
110 | ||
111 | ||
112 |
def find_repository_protected_branch |
|
113 |
protected_branch = RepositoryProtectedBranche.find_by_id(params[:id]) |
|
114 | ||
115 |
if protected_branch && protected_branch.repository_id == @repository.id |
|
116 |
@protected_branch = protected_branch |
|
117 |
elsif protected_branch |
|
118 |
render_403 |
|
119 |
else |
|
120 |
render_404 |
|
121 |
end |
|
122 |
end |
|
123 | ||
124 | ||
125 |
def set_current_tab |
|
126 |
@tab = 'repository_protected_branches' |
|
127 |
end |
|
128 | ||
129 |
end |
app/models/repository_protected_branche.rb | ||
---|---|---|
1 |
class RepositoryProtectedBranche < ActiveRecord::Base |
|
2 |
unloadable |
|
3 | ||
4 |
VALID_PERMS = [ "RW+", "RW" ] |
|
5 |
DEFAULT_PERM = "RW+" |
|
6 | ||
7 |
acts_as_list |
|
8 | ||
9 |
## Attributes |
|
10 |
attr_accessible :path, :permissions, :position, :user_list |
|
11 | ||
12 |
## Relations |
|
13 |
belongs_to :repository |
|
14 | ||
15 |
## Validations |
|
16 |
validates :repository_id, :presence => true |
|
17 |
validates :path, :presence => true, :uniqueness => { :scope => :permissions } |
|
18 |
validates :permissions, :presence => true, :inclusion => { :in => VALID_PERMS } |
|
19 |
validates :user_list, :presence => true |
|
20 | ||
21 |
## Serializations |
|
22 |
serialize :user_list, Array |
|
23 | ||
24 |
## Callbacks |
|
25 |
before_validation :remove_blank_items |
|
26 | ||
27 |
after_commit ->(obj) { obj.update_permissions }, :on => :create |
|
28 |
after_commit ->(obj) { obj.update_permissions }, :on => :update |
|
29 |
after_commit ->(obj) { obj.update_permissions }, :on => :destroy |
|
30 | ||
31 |
## Scopes |
|
32 |
default_scope order('position ASC') |
|
33 | ||
34 | ||
35 |
def self.clone_from(parent) |
|
36 |
parent = find_by_id(parent) unless parent.kind_of? RepositoryProtectedBranche |
|
37 |
copy = self.new |
|
38 |
copy.attributes = parent.attributes |
|
39 |
copy.repository = parent.repository |
|
40 | ||
41 |
copy |
|
42 |
end |
|
43 | ||
44 | ||
45 |
def available_users |
|
46 |
repository.project.member_principals.map(&:user).compact.uniq.map{ |user| user.login }.sort |
|
47 |
end |
|
48 | ||
49 | ||
50 |
def allowed_users |
|
51 |
self.user_list.map{ |user| User.find_by_login(user).gitolite_identifier }.sort |
|
52 |
end |
|
53 | ||
54 | ||
55 |
protected |
|
56 | ||
57 | ||
58 |
def update_permissions |
|
59 |
RedmineGitolite::GitHosting.logger.info { "Update branch permissions for repository : '#{repository.gitolite_repository_name}'" } |
|
60 |
RedmineGitolite::GitHosting.resync_gitolite(:update_repository, repository.id) |
|
61 |
end |
|
62 | ||
63 | ||
64 |
private |
|
65 | ||
66 | ||
67 |
def remove_blank_items |
|
68 |
self.user_list = user_list.select{ |user| !user.blank? } rescue [] |
|
69 |
end |
|
70 | ||
71 |
end |
app/services/download_git_revision.rb | ||
---|---|---|
1 |
class DownloadGitRevision |
|
2 |
unloadable |
|
3 | ||
4 |
attr_reader :commit_valid |
|
5 |
attr_reader :content_type |
|
6 |
attr_reader :filename |
|
7 | ||
8 | ||
9 |
def initialize(repository, revision, format) |
|
10 |
@repository = repository |
|
11 |
@revision = revision |
|
12 |
@format = format |
|
13 |
@project = repository.project |
|
14 | ||
15 |
@commit_valid = false |
|
16 |
@commit_id = '' |
|
17 |
@content_type = '' |
|
18 |
@filename = '' |
|
19 |
@cmd_args = [] |
|
20 | ||
21 |
validate_revision |
|
22 |
fill_data |
|
23 |
end |
|
24 | ||
25 | ||
26 |
def content |
|
27 |
RedmineGitolite::GitoliteWrapper.sudo_capture('git', "--git-dir=#{@repository.gitolite_repository_path}", 'archive', *@cmd_args, @commit_id) |
|
28 |
end |
|
29 | ||
30 | ||
31 |
private |
|
32 | ||
33 | ||
34 |
def validate_revision |
|
35 |
commit_id = nil |
|
36 | ||
37 |
# is the revision a branch? |
|
38 |
@repository.branches.each do |x| |
|
39 |
if x.to_s == @revision |
|
40 |
commit_id = x.revision |
|
41 |
break |
|
42 |
end |
|
43 |
end |
|
44 | ||
45 |
# is the revision a tag? |
|
46 |
if commit_id.nil? |
|
47 |
tags = RedmineGitolite::GitoliteWrapper.sudo_capture('git', "--git-dir=#{@repository.gitolite_repository_path}", 'tag').split |
|
48 |
tags.each do |x| |
|
49 |
if x == @revision |
|
50 |
commit_id = RedmineGitolite::GitoliteWrapper.sudo_capture('git', "--git-dir=#{@repository.gitolite_repository_path}", 'rev-list', @revision).split[0] |
|
51 |
break |
|
52 |
end |
|
53 |
end |
|
54 |
end |
|
55 | ||
56 |
# well, let check if this is a valid commit_id |
|
57 |
if commit_id.nil? |
|
58 |
commit_id = @revision |
|
59 |
end |
|
60 | ||
61 |
valid_commit = RedmineGitolite::GitoliteWrapper.sudo_capture('git', "--git-dir=#{@repository.gitolite_repository_path}", 'rev-parse', '--quiet', '--verify', commit_id).chomp.strip |
|
62 | ||
63 |
if valid_commit == '' |
|
64 |
@commit_valid = false |
|
65 |
else |
|
66 |
@commit_valid = true |
|
67 |
@commit_id = valid_commit |
|
68 |
end |
|
69 |
end |
|
70 | ||
71 | ||
72 |
def fill_data |
|
73 |
project_name = @project.to_s.parameterize.to_s |
|
74 | ||
75 |
if project_name.length == 0 |
|
76 |
project_name = "tarball" |
|
77 |
end |
|
78 | ||
79 |
case @format |
|
80 |
when 'tar' then |
|
81 |
extension = 'tar' |
|
82 |
@content_type = 'application/x-tar' |
|
83 |
@cmd_args << "--format=tar" |
|
84 | ||
85 |
when 'tar.gz' then |
|
86 |
extension = 'tar.gz' |
|
87 |
@content_type = 'application/x-gzip' |
|
88 |
@cmd_args << "--format=tar.gz" |
|
89 |
@cmd_args << "-7" |
|
90 | ||
91 |
when 'zip' then |
|
92 |
extension = 'zip' |
|
93 |
@content_type = 'application/x-zip' |
|
94 |
@cmd_args << "--format=zip" |
|
95 |
@cmd_args << "-7" |
|
96 |
end |
|
97 | ||
98 |
@filename = "#{project_name}-#{@revision}.#{extension}" |
|
99 |
end |
|
100 | ||
101 |
end |
app/services/git_notifier.rb | ||
---|---|---|
1 |
class GitNotifier |
|
2 |
unloadable |
|
3 | ||
4 | ||
5 |
attr_reader :email_prefix |
|
6 |
attr_reader :sender_address |
|
7 |
attr_reader :default_list |
|
8 |
attr_reader :mail_mapping |
|
9 | ||
10 | ||
11 |
def initialize(repository) |
|
12 |
@repository = repository |
|
13 |
@project = repository.project |
|
14 | ||
15 |
@email_prefix = '' |
|
16 |
@sender_address = '' |
|
17 |
@default_list = [] |
|
18 |
@mail_mapping = {} |
|
19 | ||
20 |
build_notifier |
|
21 |
end |
|
22 | ||
23 | ||
24 |
def mailing_list |
|
25 |
@mail_mapping.keys |
|
26 |
end |
|
27 | ||
28 | ||
29 |
private |
|
30 | ||
31 | ||
32 |
def build_notifier |
|
33 |
set_email_prefix |
|
34 |
set_sender_address |
|
35 |
set_default_list |
|
36 |
set_mail_mapping |
|
37 |
end |
|
38 | ||
39 | ||
40 |
def set_email_prefix |
|
41 |
if !@repository.git_notification.nil? && !@repository.git_notification.prefix.empty? |
|
42 |
@email_prefix = @repository.git_notification.prefix |
|
43 |
else |
|
44 |
@email_prefix = RedmineGitolite::Config.get_setting(:gitolite_notify_global_prefix) |
|
45 |
end |
|
46 |
end |
|
47 | ||
48 | ||
49 |
def set_sender_address |
|
50 |
if !@repository.git_notification.nil? && !@repository.git_notification.sender_address.empty? |
|
51 |
@sender_address = @repository.git_notification.sender_address |
|
52 |
else |
|
53 |
@sender_address = RedmineGitolite::Config.get_setting(:gitolite_notify_global_sender_address) |
|
54 |
end |
|
55 |
end |
|
56 | ||
57 | ||
58 |
def set_default_list |
|
59 |
@default_list = @project.member_principals.map(&:user).compact.uniq |
|
60 |
.select{|user| user.allowed_to?(:receive_git_notifications, @project)} |
|
61 |
.map(&:mail).uniq.sort |
|
62 |
end |
|
63 | ||
64 | ||
65 |
def set_mail_mapping |
|
66 |
mail_mapping = {} |
|
67 | ||
68 |
# First collect all project users |
|
69 |
default_users = @default_list.map{ |mail| mail_mapping[mail] = :project } |
|
70 | ||
71 |
# Then add global include list |
|
72 |
RedmineGitolite::Config.get_setting(:gitolite_notify_global_include).sort.map{ |mail| mail_mapping[mail] = :global } |
|
73 | ||
74 |
# Then filter |
|
75 |
mail_mapping = filter_list(mail_mapping) |
|
76 | ||
77 |
# Then add local include list |
|
78 |
if !@repository.git_notification.nil? && !@repository.git_notification.include_list.empty? |
|
79 |
@repository.git_notification.include_list.sort.map{ |mail| mail_mapping[mail] = :local } |
|
80 |
end |
|
81 | ||
82 |
@mail_mapping = mail_mapping |
|
83 |
end |
|
84 | ||
85 | ||
86 |
def filter_list(merged_map) |
|
87 |
mail_mapping = {} |
|
88 |
exclude_list = [] |
|
89 | ||
90 |
# Build exclusion list |
|
91 |
if !RedmineGitolite::Config.get_setting(:gitolite_notify_global_exclude).empty? |
|
92 |
exclude_list = RedmineGitolite::Config.get_setting(:gitolite_notify_global_exclude) |
|
93 |
end |
|
94 | ||
95 |
if !@repository.git_notification.nil? && !@repository.git_notification.exclude_list.empty? |
|
96 |
exclude_list = exclude_list + @repository.git_notification.exclude_list |
|
97 |
end |
|
98 | ||
99 |
exclude_list = exclude_list.uniq.sort |
|
100 | ||
101 |
merged_map.each do |mail, from| |
|
102 |
mail_mapping[mail] = from unless exclude_list.include?(mail) |
|
103 |
end |
|
104 | ||
105 |
return mail_mapping |
|
106 |
end |
|
107 | ||
108 |
end |
app/services/github_payload.rb | ||
---|---|---|
1 |
class GithubPayload |
|
2 |
unloadable |
|
3 | ||
4 | ||
5 |
attr_reader :payload |
|
6 | ||
7 | ||
8 |
def initialize(repository, payload) |
|
9 |
@repository = repository |
|
10 |
@project = repository.project |
|
11 |
@payload = build_payload(payload) |
|
12 |
end |
|
13 | ||
14 | ||
15 |
private |
|
16 | ||
17 | ||
18 |
def logger |
|
19 |
RedmineGitolite::Log.get_logger(:git_hooks) |
|
20 |
end |
|
21 | ||
22 | ||
23 |
# Returns an array of GitHub post-receive hook style hashes |
|
24 |
# http://help.github.com/post-receive-hooks/ |
|
25 |
def build_payload(refs) |
|
26 |
payload = [] |
|
27 | ||
28 |
refs.each do |ref| |
|
29 | ||
30 |
oldhead, newhead, refname = ref.split(',') |
|
31 | ||
32 |
# Only pay attention to branch updates |
|
33 |
next if !refname.match(/refs\/heads\//) |
|
34 | ||
35 |
branch = refname.gsub('refs/heads/', '') |
|
36 | ||
37 |
if newhead.match(/^0{40}$/) |
|
38 |
# Deleting a branch |
|
39 |
logger.info { "Deleting branch '#{branch}'" } |
|
40 |
next |
|
41 |
elsif oldhead.match(/^0{40}$/) |
|
42 |
# Creating a branch |
|
43 |
logger.info { "Creating branch '#{branch}'" } |
|
44 |
range = newhead |
|
45 |
else |
|
46 |
range = "#{oldhead}..#{newhead}" |
|
47 |
end |
|
48 | ||
49 |
# Grab the repository path |
|
50 |
revisions_in_range = RedmineGitolite::GitoliteWrapper.sudo_capture('git', "--git-dir=#{@repository.gitolite_repository_path}", 'rev-list', '--reverse', range) |
|
51 |
logger.debug { "Revisions in range : #{revisions_in_range.split().join(' ')}" } |
|
52 | ||
53 |
commits = [] |
|
54 | ||
55 |
revisions_in_range.split().each do |rev| |
|
56 |
logger.debug { "Revision : '#{rev.strip}'" } |
|
57 |
revision = @repository.find_changeset_by_name(rev.strip) |
|
58 |
next if revision.nil? |
|
59 | ||
60 |
revision_url = Rails.application.routes.url_helpers.url_for( |
|
61 |
:controller => 'repositories', :action => 'revision', |
|
62 |
:id => @project, :repository_id => @repository.identifier_param, :rev => rev, |
|
63 |
:only_path => false, :host => Setting['host_name'], :protocol => Setting['protocol'] |
|
64 |
) |
|
65 | ||
66 |
commit = { |
|
67 |
:id => revision.revision, |
|
68 |
:message => revision.comments, |
|
69 |
:timestamp => revision.committed_on, |
|
70 |
:added => [], |
|
71 |
:modified => [], |
|
72 |
:removed => [], |
|
73 |
:url => revision_url, |
|
74 |
:author => { |
|
75 |
:name => revision.committer.gsub(/^([^<]+)\s+.*$/, '\1'), |
|
76 |
:email => revision.committer.gsub(/^.*<([^>]+)>.*$/, '\1') |
|
77 |
} |
|
78 |
} |
|
79 | ||
80 |
revision.filechanges.each do |change| |
|
81 |
if change.action == "M" |
|
82 |
commit[:modified] << change.path |
|
83 |
elsif change.action == "A" |
|
84 |
commit[:added] << change.path |
|
85 |
elsif change.action == "D" |
|
86 |
commit[:removed] << change.path |
|
87 |
end |
|
88 |
end |
|
89 | ||
90 |
commits << commit |
|
91 |
end |
|
92 | ||
93 |
repository_url = Rails.application.routes.url_helpers.url_for( |
|
94 |
:controller => 'repositories', :action => 'show', |
|
95 |
:id => @project, :repository_id => @repository.identifier_param, |
|
96 |
:only_path => false, :host => Setting['host_name'], :protocol => Setting['protocol'] |
|
97 |
) |
|
98 | ||
99 |
payload << { |
|
100 |
:before => oldhead, |
|
101 |
:after => newhead, |
|
102 |
:ref => refname, |
|
103 |
:commits => commits, |
|
104 |
:pusher => { |
|
105 |
:name => Setting["app_title"], |
|
106 |
:email => Setting["mail_from"] |
|
107 |
}, |
|
108 |
:repository => { |
|
109 |
:description => @project.description, |
|
110 |
:fork => false, |
|
111 |
:forks => 0, |
|
112 |
:homepage => @project.homepage, |
|
113 |
:name => @repository.redmine_name, |
|
114 |
:open_issues => @project.issues.open.length, |
|
115 |
:watchers => 0, |
|
116 |
:private => !@project.is_public, |
|
117 |
:url => repository_url, |
|
118 |
:owner => { |
|
119 |
:name => Setting["app_title"], |
|
120 |
:email => Setting["mail_from"] |
|
121 |
} |
|
122 |
} |
|
123 |
} |
|
124 |
end |
|
125 | ||
126 |
return payload |
|
127 |
end |
|
128 | ||
129 |
end |
app/services/hooks/git_mirrors.rb | ||
---|---|---|
1 |
module Hooks |
|
2 |
class GitMirrors |
|
3 |
unloadable |
|
4 | ||
5 | ||
6 |
def initialize(repository, payload) |
|
7 |
@repository = repository |
|
8 |
@project = repository.project |
|
9 |
@payload = payload |
|
10 |
end |
|
11 | ||
12 | ||
13 |
def execute |
|
14 |
call_mirrors |
|
15 |
end |
|
16 | ||
17 | ||
18 |
private |
|
19 | ||
20 | ||
21 |
def logger |
|
22 |
RedmineGitolite::Log.get_logger(:git_hooks) |
|
23 |
end |
|
24 | ||
25 | ||
26 |
def call_mirrors |
|
27 |
y = "" |
|
28 | ||
29 |
## Push to each mirror |
|
30 |
if @repository.mirrors.active.any? |
|
31 | ||
32 |
logger.info { "Notifying mirrors about changes to this repository :" } |
|
33 |
y << "\nNotifying mirrors about changes to this repository :\n" |
|
34 | ||
35 |
@repository.mirrors.active.each do |mirror| |
|
36 |
if mirror.needs_push(@payload) |
|
37 |
logger.info { "Pushing changes to #{mirror.url} ... " } |
|
38 |
y << " - Pushing changes to #{mirror.url} ... " |
|
39 | ||
40 |
push_failed, push_message = mirror.push |
|
41 | ||
42 |
if push_failed |
|
43 |
logger.error { "Failed!" } |
|
44 |
logger.error { "#{push_message}" } |
|
45 |
y << " [failure]\n" |
|
46 |
else |
|
47 |
logger.info { "Succeeded!" } |
|
48 |
y << " [success]\n" |
|
49 |
end |
|
50 |
end |
|
51 |
end |
|
52 |
end |
|
53 | ||
54 |
return y |
|
55 |
end |
|
56 | ||
57 |
end |
|
58 |
end |
app/services/hooks/github_issues_sync.rb | ||
---|---|---|
1 |
require 'json' |
|
2 | ||
3 |
module Hooks |
|
4 |
class GithubIssuesSync |
|
5 |
unloadable |
|
6 | ||
7 |
include HttpHelper |
|
8 | ||
9 | ||
10 |
def initialize(project, params) |
|
11 |
@project = project |
|
12 |
@params = params |
|
13 |
end |
|
14 | ||
15 | ||
16 |
def execute |
|
17 |
sync_with_github |
|
18 |
end |
|
19 | ||
20 | ||
21 |
private |
|
22 | ||
23 | ||
24 |
def logger |
|
25 |
RedmineGitolite::Log.get_logger(:git_hooks) |
|
26 |
end |
|
27 | ||
28 | ||
29 |
def sync_with_github |
|
30 |
github_issue = GithubIssue.find_by_github_id(@params[:issue][:id]) |
|
31 |
redmine_issue = Issue.find_by_subject(@params[:issue][:title]) |
|
32 |
create_relation = false |
|
33 | ||
34 |
## We don't have stored relation |
|
35 |
if github_issue.nil? |
|
36 | ||
37 |
## And we don't have issue in Redmine |
|
38 |
if redmine_issue.nil? |
|
39 |
create_relation = true |
|
40 |
redmine_issue = create_redmine_issue |
|
41 |
else |
|
42 |
## Create relation and update issue |
|
43 |
create_relation = true |
|
44 |
redmine_issue = update_redmine_issue(redmine_issue) |
|
45 |
end |
|
46 |
else |
|
47 |
## We have one relation, update issue |
|
48 |
redmine_issue = update_redmine_issue(github_issue.issue) |
|
49 |
end |
|
50 | ||
51 |
if create_relation |
|
52 |
github_issue = GithubIssue.new |
|
53 |
github_issue.github_id = @params[:issue][:id] |
|
54 |
github_issue.issue_id = redmine_issue.id |
|
55 |
github_issue.save! |
|
56 |
end |
|
57 | ||
58 |
if @params.has_key?(:comment) |
|
59 |
issue_journal = GithubComment.find_by_github_id(@params[:comment][:id]) |
|
60 | ||
61 |
if issue_journal.nil? |
|
62 |
issue_journal = create_issue_journal(github_issue.issue) |
|
63 | ||
64 |
github_comment = GithubComment.new |
|
65 |
github_comment.github_id = @params[:comment][:id] |
|
66 |
github_comment.journal_id = issue_journal.id |
|
67 |
github_comment.save! |
|
68 |
end |
|
69 |
end |
|
70 |
end |
|
71 | ||
72 | ||
73 |
def create_redmine_issue |
|
74 |
logger.info { "Github Issues Sync : create new issue" } |
|
75 | ||
76 |
issue = Issue.new |
|
77 |
issue.project_id = @project.id |
|
78 |
issue.tracker_id = @project.trackers.find(:first).try(:id) |
|
79 |
issue.subject = @params[:issue][:title].chomp[0, 255] |
|
80 |
issue.description = @params[:issue][:body] |
|
81 |
issue.updated_on = @params[:issue][:updated_at] |
|
82 |
issue.created_on = @params[:issue][:created_at] |
|
83 | ||
84 |
## Get user mail |
|
85 |
user = find_user(@params[:issue][:user][:url]) |
|
86 |
issue.author = user |
|
87 | ||
88 |
issue.save! |
|
89 |
return issue |
|
90 |
end |
|
91 | ||
92 | ||
93 |
def create_issue_journal(issue) |
|
94 |
logger.info { "Github Issues Sync : create new journal for issue '##{issue.id}'" } |
|
95 | ||
96 |
journal = Journal.new |
|
97 |
journal.journalized_id = issue.id |
|
98 |
journal.journalized_type = 'Issue' |
|
99 |
journal.notes = @params[:comment][:body] |
|
100 |
journal.created_on = @params[:comment][:created_at] |
|
101 | ||
102 |
## Get user mail |
|
103 |
user = find_user(@params[:comment][:user][:url]) |
|
104 |
journal.user_id = user.id |
|
105 | ||
106 |
journal.save! |
|
107 |
return journal |
|
108 |
end |
|
109 | ||
110 | ||
111 |
def update_redmine_issue(issue) |
|
112 |
logger.info { "Github Issues Sync : update issue '##{issue.id}'" } |
|
113 | ||
114 |
if @params[:issue][:state] == 'closed' |
|
115 |
issue.status_id = 5 |
|
116 |
else |
|
117 |
issue.status_id = 1 |
|
118 |
end |
|
119 | ||
120 |
issue.subject = @params[:issue][:title].chomp[0, 255] |
|
121 |
issue.description = @params[:issue][:body] |
|
122 |
issue.updated_on = @params[:issue][:updated_at] |
|
123 | ||
124 |
issue.save! |
|
125 |
return issue |
|
126 |
end |
|
127 | ||
128 | ||
129 |
def find_user(url) |
|
130 |
post_failed, user_data = post_data(url, "", :method => :get) |
|
131 |
user_data = JSON.parse(user_data) |
|
132 | ||
133 |
user = User.find_by_mail(user_data['email']) |
|
134 | ||
135 |
if user.nil? |
|
136 |
logger.info { "Github Issues Sync : cannot find user '#{user_data['email']}' in Redmine, use anonymous" } |
|
137 |
user = User.anonymous |
|
138 |
user.mail = user_data['email'] |
|
139 |
user.firstname = user_data['name'] |
|
140 |
user.lastname = user_data['login'] |
|
141 |
end |
|
142 | ||
143 |
return user |
|
144 |
end |
|
145 | ||
146 |
end |
|
147 |
end |
app/services/hooks/http_helper.rb | ||
---|---|---|
1 |
require 'net/http' |
|
2 |
require 'net/https' |
|
3 |
require 'uri' |
|
4 | ||
5 |
module Hooks |
|
6 |
module HttpHelper |
|
7 |
unloadable |
|
8 | ||
9 |
def post_data(url, payload, opts={}) |
|
10 |
uri = URI(url) |
|
11 |
http = Net::HTTP.new(uri.host, uri.port) |
|
12 | ||
13 |
if uri.scheme == 'https' |
|
14 |
http.use_ssl = true |
|
15 |
http.verify_mode = OpenSSL::SSL::VERIFY_NONE |
|
16 |
end |
|
17 | ||
18 |
if opts[:method] == :post |
|
19 |
request = Net::HTTP::Post.new(uri.request_uri) |
|
20 |
request.set_form_data({"payload" => payload.to_json}) |
|
21 |
else |
|
22 |
request = Net::HTTP::Get.new(uri.request_uri) |
|
23 |
end |
|
24 | ||
25 |
message = "" |
|
26 | ||
27 |
begin |
|
28 |
res = http.start {|openhttp| openhttp.request request} |
|
29 |
if !res.is_a?(Net::HTTPSuccess) |
|
30 |
message = "Return code : #{res.code} (#{res.message})." |
|
31 |
failed = true |
|
32 |
else |
|
33 |
message = res.body |
|
34 |
failed = false |
|
35 |
end |
|
36 |
rescue => e |
|
37 |
message = "Exception : #{e.message}" |
|
38 |
failed = true |
|
39 |
end |
|
40 | ||
41 |
return failed, message |
|
42 |
end |
|
43 | ||
44 |
end |
|
45 |
end |
app/services/hooks/redmine.rb | ||
---|---|---|
1 |
module Hooks |
|
2 |
class Redmine |
|
3 |
unloadable |
|
4 | ||
5 | ||
6 |
def initialize(repository) |
|
7 |
@repository = repository |
|
8 |
end |
|
9 | ||
10 | ||
11 |
def execute |
|
12 |
fetch_changesets |
|
13 |
end |
|
14 | ||
15 | ||
16 |
private |
|
17 | ||
18 | ||
19 |
def logger |
|
20 |
RedmineGitolite::Log.get_logger(:git_hooks) |
|
21 |
end |
|
22 | ||
23 | ||
24 |
def fetch_changesets |
|
25 |
## Fetch commits from the repository |
|
26 |
y = "" |
|
27 | ||
28 |
logger.info { "Fetching changesets for '#{@repository.redmine_name}' repository ... " } |
|
29 |
y << " - Fetching changesets for '#{@repository.redmine_name}' repository ... " |
|
30 | ||
31 |
begin |
|
32 |
@repository.fetch_changesets |
|
33 |
logger.info { "Succeeded!" } |
|
34 |
y << " [success]\n" |
|
35 |
rescue ::Redmine::Scm::Adapters::CommandFailed => e |
|
36 |
logger.error { "Failed!" } |
|
37 |
logger.error { "Error during fetching changesets : #{e.message}" } |
|
38 |
y << " [failure]\n" |
|
39 |
rescue => e |
|
40 |
logger.error { "Failed!" } |
|
41 |
logger.error { "Error after fetching changesets : #{e.message}" } |
|
42 |
y << " [failure]\n" |
|
43 |
end |
|
44 | ||
45 |
return y |
|
46 |
end |
|
47 | ||
48 |
end |
|
49 |
end |
app/services/hooks/webservices.rb | ||
---|---|---|
1 |
module Hooks |
|
2 |
class Webservices |
|
3 |
unloadable |
|
4 | ||
5 |
include HttpHelper |
|
6 | ||
7 | ||
8 |
def initialize(repository, payload) |
|
9 |
@repository = repository |
|
10 |
@project = repository.project |
|
11 |
@payload = payload |
|
12 |
end |
|
13 | ||
14 | ||
15 |
def execute |
|
16 |
call_webservices |
|
17 |
end |
|
18 | ||
19 | ||
20 |
private |
|
21 | ||
22 | ||
23 |
def logger |
|
24 |
RedmineGitolite::Log.get_logger(:git_hooks) |
|
25 |
end |
|
26 | ||
27 | ||
28 |
def call_webservices |
|
29 |
y = "" |
|
30 | ||
31 |
## Post to each post-receive URL |
|
32 |
if @repository.post_receive_urls.active.any? |
|
33 | ||
34 |
logger.info { "Notifying post receive urls about changes to this repository :" } |
|
35 |
y << "\nNotifying post receive urls about changes to this repository :\n" |
|
36 | ||
37 |
@repository.post_receive_urls.active.each do |post_receive_url| |
|
38 |
if payloads = post_receive_url.needs_push(@payload) |
|
39 | ||
40 |
method = (post_receive_url.mode == :github) ? :post : :get |
|
41 | ||
42 |
if method == :post && post_receive_url.split_payloads? |
|
43 |
payloads.each do |payload| |
|
44 |
logger.info { "Notifying #{post_receive_url.url} for '#{payload[:ref]}' ... " } |
|
45 |
y << " - Notifying #{post_receive_url.url} for '#{payload[:ref]}' ... " |
|
46 | ||
47 |
post_failed, post_message = post_data(post_receive_url.url, payload, :method => method) |
|
48 | ||
49 |
if post_failed |
|
50 |
logger.error { "Failed!" } |
|
51 |
logger.error { "#{post_message}" } |
|
52 |
y << " [failure]\n" |
|
53 |
else |
|
54 |
logger.info { "Succeeded!" } |
|
55 |
y << " [success]\n" |
|
56 |
end |
|
57 |
end |
|
58 |
else |
|
59 |
logger.info { "Notifying #{post_receive_url.url} ... " } |
|
60 |
y << " - Notifying #{post_receive_url.url} ... " |
|
61 | ||
62 |
post_failed, post_message = post_data(post_receive_url.url, @payload, :method => method) |
|
63 | ||
64 |
if post_failed |
|
65 |
logger.error { "Failed!" } |
|
66 |
logger.error { "#{post_message}" } |
|
67 |
y << " [failure]\n" |
|
68 |
else |
|
69 |
logger.info { "Succeeded!" } |
|
70 |
y << " [success]\n" |
|
71 |
end |
|
72 |
end |
|
73 |
end |
|
74 |
end |
|
75 |
end |
|
76 | ||
77 |
return y |
|
78 |
end |
|
79 | ||
80 |
end |
|
81 |
end |
app/views/gitolite_public_keys/_form.html.erb | ||
---|---|---|
1 |
<div id="validation_messages"><%= error_messages_for 'gitolite_public_key' %></div> |
|
2 | ||
3 |
<%= labelled_form_for :gitolite_public_key, gitolite_public_key, |
|
4 |
:url => {:controller => 'gitolite_public_keys', :action => 'create', :user_id => params[:id], :tab => params[:id]&&'keys'}, |
|
5 |
:html => {:method => :post} do |f| %> |
|
6 | ||
7 |
<p><%= f.text_field :title, :label => :label_identifier_can_be_arbitrary, :required => true, :style => 'width: 97%;' %></p> |
|
8 | ||
9 |
<% if can_create_deployment_keys_for_some_project(@user) %> |
|
10 |
<p> |
|
11 |
<%= f.select :key_type, options_for_select( |
|
12 |
[ |
|
13 |
[ l(:label_user_key), 0 ], |
|
14 |
[ l(:label_deploy_key), 1 ] |
|
15 |
], |
|
16 |
), |
|
17 |
{ :required => true, :label => :label_key_type }, |
|
18 |
{ :class => 'select_key_type' } %> |
|
19 | ||
20 | ||
21 |
</p> |
|
22 | ||
23 |
<div id="key_type_options" style="display: none;"> |
|
24 |
<p> |
|
25 |
<%= f.check_box :delete_when_unused, :required => true, :label => :label_deployment_credential_delete_when_unused %> |
|
26 |
</p> |
|
27 |
</div> |
|
28 |
<% end %> |
|
29 | ||
30 |
<p> |
|
31 |
<%= f.text_area :key, :label => :label_public_key, :required => true, |
|
32 |
:style => "width: 97%; height: 200px; overflow: auto;", |
|
33 |
:cols => nil, |
|
34 |
:rows => nil %> |
|
35 |
</p> |
|
36 | ||
37 | ||
38 | ||
39 |
<em><%= l(:label_cut_and_paste) %></em><br /><br /> |
|
40 |
<%= submit_tag l(:button_create), :name => 'create_button' %> |
|
41 |
<%= submit_tag l(:button_cancel), :name => 'cancel_button' %> |
|
42 | ||
43 |
<% end %> |
app/views/gitolite_public_keys/index.html.erb | ||
---|---|---|
1 |
<%= render :partial => 'gitolite_public_keys/view' %> |
app/views/repositories/_edit_bottom.html.erb | ||
---|---|---|
1 |
<% if @repository.is_a?(Repository::Git) %> |
|
2 | ||
3 |
<div id="repository-tabs"> |
|
4 |
<ul> |
|
5 |
<% if user_allowed_to(:view_deployment_keys, @repository.project) %> |
|
6 |
<li id="tab-repository_deployment_credentials"> |
|
7 |
<%= link_to label_with_icon(l(:label_deployment_credentials), 'fa-ticket'), |
|
8 |
repository_deployment_credentials_path(@repository) %> |
|
9 |
</li> |
|
10 |
<% end %> |
|
11 | ||
12 |
<% if user_allowed_to(:view_repository_git_notifications, @repository.project) %> |
|
13 |
<li id="tab-repository_git_notifications"> |
|
14 |
<%= link_to label_with_icon(l(:label_git_notifications), 'fa-envelope'), |
|
15 |
repository_git_notifications_path(@repository) %> |
|
16 |
</li> |
|
17 |
<% end %> |
|
18 | ||
19 |
<% if user_allowed_to(:view_repository_mirrors, @repository.project) %> |
|
20 |
<li id="tab-repository_mirrors"> |
|
21 |
<%= link_to label_with_icon(l(:label_repository_mirrors), 'fa-sitemap'), |
|
22 |
repository_mirrors_path(@repository) %> |
|
23 |
</li> |
|
24 |
<% end %> |
|
25 | ||
26 |
<% if user_allowed_to(:view_repository_post_receive_urls, @repository.project) %> |
|
27 |
<li id="tab-repository_post_receive_urls"> |
|
28 |
<%= link_to label_with_icon(l(:label_post_receive_urls), 'fa-external-link'), |
|
29 |
repository_post_receive_urls_path(@repository) %> |
|
30 |
</li> |
|
31 |
<% end %> |
|
32 | ||
33 |
<% if user_allowed_to(:view_repository_git_config_keys, @repository.project) %> |
|
34 |
<li id="tab-repository_git_config_keys"> |
|
35 |
<%= link_to label_with_icon(l(:label_git_config_keys), 'fa-th-list'), |
|
36 |
repository_git_config_keys_path(@repository) %> |
|
37 |
</li> |
|
38 |
<% end %> |
|
39 | ||
40 |
<% if user_allowed_to(:view_repository_protected_branches, @repository.project) %> |
|
41 |
<li id="tab-repository_protected_branches"> |
|
42 |
<%= link_to "<i class=\"fa fa-lock\"></i>".html_safe + l(:label_protected_branches), |
|
43 |
repository_protected_branches_path(@repository) %> |
|
44 |
</li> |
|
45 |
<% end %> |
|
46 |
</ul> |
|
47 |
</div> |
|
48 | ||
49 |
<div id="modal-box"></div> |
|
50 |
<div id="modal-box-close-only"></div> |
|
51 | ||
52 |
<% content_for :header_tags do %> |
|
53 |
<%= stylesheet_link_tag 'font_awesome', :plugin => 'redmine_bootstrap_kit' %> |
|
54 |
<%= stylesheet_link_tag 'jquery_tag_it', :plugin => 'redmine_bootstrap_kit' %> |
|
55 |
<%= stylesheet_link_tag 'bootstrap/bootstrap_custom', :plugin => 'redmine_bootstrap_kit' %> |
|
56 |
<%= stylesheet_link_tag 'bootstrap/bootstrap_label', :plugin => 'redmine_bootstrap_kit' %> |
|
57 |
<%= stylesheet_link_tag 'bootstrap/bootstrap_tables', :plugin => 'redmine_bootstrap_kit' %> |
|
58 | ||
59 |
<%= javascript_include_tag 'jquery_tag_it', :plugin => 'redmine_bootstrap_kit' %> |
|
60 |
<%= javascript_include_tag 'bootstrap', :plugin => 'redmine_bootstrap_kit' %> |
|
61 | ||
62 |
<%= javascript_tag do %> |
|
63 | ||
64 |
function post_mode_change(elem) { |
|
65 |
if (!elem) return; |
|
66 |
var idx = elem.selectedIndex; |
|
67 |
if (idx == 0) { |
|
68 |
$('#payload_options').show(); |
|
69 |
} else { |
|
70 |
$('#payload_options').hide(); |
|
71 |
} |
|
72 |
} |
|
73 | ||
74 |
function push_mode_change(elem) { |
|
75 |
if (!elem) return; |
|
76 |
var idx = elem.selectedIndex; |
|
77 |
if (idx == 0) { |
|
78 |
$('#ref_spec_options').hide(); |
|
79 |
} else { |
|
80 |
$('#ref_spec_options').show(); |
|
81 |
} |
|
82 |
} |
|
83 | ||
84 |
function key_mode_change(elem) { |
|
85 |
if (!elem) return; |
|
86 |
var idx = elem.selectedIndex; |
|
87 |
if (idx == 0) { |
|
88 |
$('#new_key_window').show(); |
|
89 |
} else { |
|
90 |
$('#new_key_window').hide(); |
|
91 |
} |
|
92 |
} |
|
93 | ||
94 |
var modals = Object(); |
|
95 |
modals.label_save = '<%= l(:button_save) %>'; |
|
96 |
modals.label_cancel = '<%= l(:button_cancel) %>'; |
|
97 |
modals.label_ok = '<%= l(:button_ok) %>'; |
|
98 |
modals.modal_list = []; |
|
99 |
modals.modal_list[0] = {'source': '.modal-box', 'target': '#modal-box', 'mode': 'standard'}; |
|
100 |
modals.modal_list[1] = {'source': '.modal-box-close-only', 'target': '#modal-box-close-only', 'mode': 'close-only'}; |
|
101 | ||
102 |
$(document).ready(function() { |
|
103 |
var all_tabs = $("#repository-tabs li"); |
|
104 |
var active_tab = ''; |
|
105 | ||
106 |
all_tabs.each(function(){ |
|
107 |
if ($(this).attr('id').replace('tab-', '') == '<%= @tab %>') { |
|
108 |
active_tab = all_tabs.index(this); |
|
109 |
} |
|
110 |
}); |
|
111 | ||
112 |
$("#repository-tabs").tabs({ |
|
113 |
active: active_tab, |
|
114 |
activate: function(event, ui) { |
|
115 |
var new_tab_name = $(ui.newTab).attr('id').replace('tab-', ''); |
|
116 |
if ("replaceState" in window.history) { |
|
117 |
window.history.replaceState(null, document.title, 'edit?tab=' + new_tab_name); |
|
118 |
} |
|
119 |
} |
|
120 |
}); |
|
121 |
}); |
|
122 |
<% end %> |
|
123 |
<% end %> |
|
124 | ||
125 |
<% end %> |
app/views/repositories/_edit_top.html.erb | ||
---|---|---|
1 |
<% if @repository.is_a?(Repository::Git) %> |
|
2 |
<div class="git_hosting box"> |
|
3 |
<h3><%= l(:label_repository_access_url) %></h3> |
|
4 |
<%= render :partial => 'common/git_urls', :locals => {:repository => @repository} %> |
|
5 |
</div> |
|
6 |
<% end %> |
app/views/repositories/_git_form.html.erb | ||
---|---|---|
1 |
<% content_for :header_tags do %> |
|
2 |
<%= stylesheet_link_tag 'bootstrap/bootstrap_switch', :plugin => 'redmine_bootstrap_kit' %> |
|
3 |
<%= javascript_include_tag 'plugins/bootstrap_switch', :plugin => 'redmine_bootstrap_kit' %> |
|
4 |
<%= javascript_include_tag 'bootstrap', :plugin => 'redmine_bootstrap_kit' %> |
|
5 |
<% end %> |
|
6 | ||
7 |
<%= javascript_tag do %> |
|
8 | ||
9 |
$(document).ready(function() { |
|
10 | ||
11 |
// Actually this takes the parent <p> mark |
|
12 |
var default_checkbox = $('#repository_is_default').parent(); |
|
13 | ||
14 |
<% if @project.repository.nil? %> |
|
15 |
// The default repository is not set, nothing to do... |
|
16 | ||
17 |
<% elsif @project.repository == @repository %> |
|
18 |
var content = $('<%= content_tag :p do -%> |
|
19 |
<%= hidden_field_tag "repository[is_default]", "1" -%> |
|
20 |
<%= content_tag :label, l(:field_repository_is_default) -%> |
|
21 |
<%= content_tag :span, l(:label_yes), :class => 'label label-success' -%> |
|
22 |
<% end -%>'); |
|
23 | ||
24 |
content.insertAfter(default_checkbox); |
|
25 |
default_checkbox.remove(); |
|
26 |
$('#repository_identifier').parent().remove(); |
|
27 |
<% else %> |
|
28 |
var content = $('<%= content_tag :p do -%> |
|
29 |
<%= hidden_field_tag "repository[is_default]", "0" -%> |
|
30 |
<%= content_tag :label, l(:field_repository_is_default) -%> |
|
31 |
<%= content_tag :span, l(:label_no), :class => 'label' -%> |
|
32 |
<% end -%>'); |
|
33 | ||
34 |
content.insertAfter(default_checkbox); |
|
35 |
default_checkbox.remove(); |
|
36 |
<% end %> |
|
37 | ||
38 |
}); |
|
39 | ||
40 |
<% end %> |
|
41 | ||
42 |
<% if @repository.is_a?(Repository::Git) %> |
|
43 | ||
44 |
<%= javascript_tag do %> |
|
45 | ||
46 |
function moveGitOptionsDiv(){ |
|
47 |
if ( $('#git_hosting_settings').length == 0 ) { |
|
48 |
// Set selectors |
|
49 |
var original_div = $('#repository_git_options').parent(); |
|
50 |
var new_div = $('#repository_git_options'); |
|
51 | ||
52 |
// Wrap the original_div in a new div |
|
53 |
original_div.wrap('<div id="git_hosting_settings" class="box tabular">'); |
|
54 | ||
55 |
// Remove original css class |
|
56 |
original_div.removeClass('box tabular'); |
|
57 | ||
58 |
// Add new css class |
|
59 |
original_div.addClass('split'); |
|
60 | ||
61 |
// Insert our div after the original one |
|
62 |
new_div.insertAfter(original_div); |
|
63 | ||
64 |
$('<div style="display: block; clear: both;"></div>').insertAfter(new_div); |
|
65 | ||
66 |
new_div.show(); |
|
67 |
} |
|
68 |
} |
|
69 | ||
70 |
$(document).ready(function() { |
|
71 |
$('#repository_url').parent().remove(); |
|
72 |
moveGitOptionsDiv(); |
|
73 | ||
74 |
$('.bootstrap-switch').each(function(index, element) { |
|
75 |
if (!$(element).children('div').length > 0){ |
|
76 |
installBootstrapSwitch(element); |
|
77 |
} |
|
78 |
}); |
|
79 |
}); |
|
80 |
<% end %> |
|
81 | ||
82 |
<div id="repository_git_options" class="split" style="display: none;"> |
|
83 | ||
84 |
<h3><%= l(:label_repository_options) %></h3> |
|
85 | ||
86 |
<% |
|
87 |
selected = "false" |
|
88 |
if @repository.extra[:git_daemon] |
|
89 |
selected = "true" |
|
90 |
elsif @project.is_public && RedmineGitolite::Config.get_setting(:gitolite_daemon_by_default, true) |
|
91 |
selected = "true" |
|
92 |
end |
|
93 |
%> |
|
94 | ||
95 |
<p> |
|
96 |
<label><%= l(:label_enable_git_daemon) %></label> |
|
97 |
<span class="bootstrap-switch switch-small" data-on="primary" data-off="default" data-on-label="<%= l(:label_yes) %>" data-off-label="<%= l(:label_no) %>"> |
|
98 |
<%= hidden_field_tag "extra[git_daemon]", "false" %> |
|
99 |
<%= check_box_tag "extra[git_daemon]", selected, (selected == "true" ? true : false), disabled: !@project.is_public %> |
|
100 |
</span> |
|
101 |
</p> |
|
102 | ||
103 |
<% if user_allowed_to(:create_repository_git_notifications, @repository.project) %> |
|
104 |
<p> |
|
105 |
<label><%= l(:label_enable_git_notify) %></label> |
|
106 |
<span class="bootstrap-switch switch-small" data-on="primary" data-off="default" data-on-label="<%= l(:label_yes) %>" data-off-label="<%= l(:label_no) %>"> |
|
107 |
<%= hidden_field_tag "extra[git_notify]", "false" %> |
|
108 |
<%= check_box_tag "extra[git_notify]", @repository.extra[:git_notify], @repository.extra[:git_notify] %> |
|
109 |
</span> |
|
110 |
</p> |
|
111 |
<% end %> |
|
112 | ||
113 |
<% if user_allowed_to(:create_repository_protected_branches, @repository.project) %> |
|
114 |
<p> |
|
115 |
<label><%= l(:label_enable_protected_branches) %></label> |
|
116 |
<span class="bootstrap-switch switch-small" data-on="primary" data-off="default" data-on-label="<%= l(:label_yes) %>" data-off-label="<%= l(:label_no) %>"> |
|
117 |
<%= hidden_field_tag "extra[protected_branch]", "false" %> |
|
118 |
<%= check_box_tag "extra[protected_branch]", @repository.extra[:protected_branch], @repository.extra[:protected_branch] %> |
|
119 |
</span> |
|
120 |
</p> |
|
121 |
<% end %> |
|
122 | ||
123 |
<p> |
|
124 |
<%= label_tag "extra[git_http]", l(:label_enable_smart_http) %> |
|
125 |
<%= select_tag "extra[git_http]", options_for_select([ |
|
126 |
[l(:label_disabled), "0"], |
|
127 |
[l(:label_http_only), "3"], |
|
128 |
[l(:label_https_only), "1"], |
|
129 |
[l(:label_https_and_http), "2"] |
|
130 |
], :selected => @repository.extra[:git_http].to_s) %> |
|
131 |
</p> |
|
132 | ||
133 |
<p> |
|
134 |
<%= label_tag "", l(:label_repository_default_branch) %> |
|
135 |
<% if !@repository.new_record? && !@repository.branches.empty? %> |
|
136 |
<%= select_tag "extra[default_branch]", options_for_select(@repository.branches.collect{ |b| [b.to_s, b.to_s] }, :selected => @repository.branches.find{ |b| b.is_default}.to_s) %> |
|
137 |
<% else %> |
|
138 |
<span class="label label-info"><%= @repository.extra[:default_branch] %></span> |
|
139 |
<% end %> |
|
140 |
</p> |
|
141 | ||
142 |
<p> |
|
143 |
<%= label_tag "", l(:label_mirroring_keys_installed) %> |
|
144 |
<%= image_tag (RedmineGitolite::GitoliteWrapper.mirroring_keys_installed? ? 'true.png' : 'exclamation.png') %> |
|
145 |
</p> |
|
146 | ||
147 |
<% if !@repository.new_record? %> |
|
148 |
<p> |
|
149 |
<%= label_tag "", l(:label_repository_exists_in_gitolite) %> |
|
150 |
<%= image_tag (@repository.exists_in_gitolite? ? 'true.png' : 'exclamation.png') %> |
|
151 |
</p> |
|
152 |
<p> |
|
153 |
<label><%= l(:label_browse_repository) %></label> |
|
154 |
<%= link_to h(@repository.url), {:controller => 'repositories', :action => 'show', :id => @project, :repository_id => @repository.identifier_param} %> |
|
155 |
</p> |
|
156 |
<% else %> |
|
157 |
<%= javascript_tag do %> |
|
158 |
$(document).ready(function() { |
|
159 |
var content = $('<%= content_tag :p do -%> |
|
160 |
<%= hidden_field_tag "repository[create_readme]", "false" -%> |
|
161 |
<%= content_tag :label, l(:label_init_repo_with_readme) -%> |
|
162 |
<%= check_box_tag "repository[create_readme]", "true", RedmineGitolite::Config.get_setting(:init_repositories_on_create, true) -%> |
|
163 |
<% end -%>'); |
|
164 | ||
165 |
if ($('#repository_create_readme').length == 0) { |
|
166 |
content.insertAfter($('#repository_identifier').parent()); |
|
167 |
} |
|
168 |
}); |
|
169 |
<% end %> |
|
170 |
<% end %> |
|
171 | ||
172 |
</div> |
|
173 | ||
174 |
<% end %> |
app/views/repositories/_sidebar.html.erb | ||
---|---|---|
1 |
<%= javascript_tag do %> |
|
2 |
$(document).ready(function() { |
|
3 |
$('#sidebar p').remove(); |
|
4 |
}); |
|
5 |
<% end %> |
|
6 | ||
7 | ||
8 | ||
9 |
<ul class="repository git"> |
|
10 |
<% @repositories.sort.each do |repo| %> |
|
11 |
<li class="repository git"><%= link_to h(repo.name), {:controller => 'repositories', :action => 'show', :id => @project, :repository_id => repo.identifier_param, :rev => nil, :path => nil}, |
|
12 |
:class => [ 'repository', (repo == @repository ? 'selected' : ''), @repository.type.split('::')[1].downcase ].join(' ') %> |
|
13 |
</li> |
|
14 |
<% end %> |
|
15 |
</ul> |
|
16 | ||
17 |
<% if @repository.is_a?(Repository::Git) && RedmineGitolite::Config.get_setting(:show_repositories_url, true) %> |
|
18 |
<div class="git_hosting_urls"> |
|
19 |
<h3><%= l(:label_repository_access_url) %></h3> |
|
20 |
<%= render :partial => 'common/git_urls', :locals => {:repository => @repository} %> |
|
21 |
</div> |
|
22 |
<% end %> |
|
23 | ||
24 |
<%= render :partial => 'repositories/download_revision' %> |
app/views/repository_protected_branches/_form.html.erb | ||
---|---|---|
1 |
<div id="validation_messages_protected_branch"><%= error_messages_for 'protected_branch' %></div> |
|
2 | ||
3 |
<div class="box"> |
|
4 |
<p><%= f.text_field :path, :required => true, :size => 65, :label => l(:label_branch_path) %></p> |
|
5 |
<p><%= f.select :permissions, options_for_select(RepositoryProtectedBranche::VALID_PERMS, @protected_branch.permissions), |
|
6 |
:required => true, |
|
7 |
:label => :label_permissions %> |
|
8 |
</p> |
|
9 | ||
10 |
<%= hidden_field_tag "repository_protected_branche[user_list][]", "" %> |
|
11 | ||
12 |
<p><label for="repository_protected_branche[user_list]"><%= l(:label_user_list) %> :</label></p> |
|
13 |
<ul id="user_list"> |
|
14 |
<% if @protected_branch.user_list.any? %> |
|
15 |
<% @protected_branch.user_list.each do |item| %> |
|
16 |
<li><%= item %></li> |
|
17 |
<% end %> |
|
18 |
<% end %> |
|
19 |
</ul> |
|
20 |
</div> |
|
21 | ||
22 |
<%= javascript_tag do %> |
|
23 |
var user_list = <%= raw @protected_branch.available_users.to_json %>; |
|
24 | ||
25 |
function loadTagIt(target){ |
|
26 | ||
27 |
$('#' + target).gtagit({ |
|
28 |
autocomplete: {source: function(request, resolve) { |
|
29 |
// fetch new values with request.resolve |
|
30 |
resolve(user_list); |
|
31 |
} |
|
32 |
}, |
|
33 |
afterTagAdded: function(event, ui) { |
|
34 |
var value = ui.tag.children('input:hidden').val(); |
|
35 |
user_list = user_list.filter(function(v) { return v != value;}); |
|
36 |
$(".ui-dialog-content").dialog("option", "position", ['center', 'center']).animate('slow'); |
|
37 |
}, |
|
38 |
afterTagRemoved: function(event, ui) { |
|
39 |
var value = ui.tag.children('input:hidden').val(); |
|
40 |
user_list.push(value); |
|
41 |
$(".ui-dialog-content").dialog("option", "position", ['center', 'center']).animate('slow'); |
|
42 |
}, |
|
43 |
showAutocompleteOnFocus: true, |
|
44 |
placeholderText: '+ add user', |
|
45 |
allowDuplicates: false, |
|
46 |
caseSensitive: false, |
|
47 |
fieldName: 'repository_protected_branche[' + target + '][]', |
|
48 |
}); |
|
49 | ||
50 |
} |
|
51 | ||
52 |
$(document).ready(function() { |
|
53 |
loadTagIt('user_list'); |
|
54 |
}); |
|
55 |
<% end %> |
app/views/repository_protected_branches/edit.html.erb | ||
---|---|---|
1 |
<% if !@is_xhr %> |
|
2 |
<h2><%= l(:label_protected_branch_edit) %></h2> |
|
3 |
<% end %> |
|
4 | ||
5 |
<%= labelled_form_for :repository_protected_branche, @protected_branch, |
|
6 |
:url => repository_protected_branch_path(@repository, @protected_branch), |
|
7 |
:html => { :method => :put, :class => 'tabular', :remote => @is_xhr } do |f| %> |
|
8 | ||
9 |
<%= render :partial => 'form', :locals => { :f => f } %> |
|
10 | ||
11 |
<% if !@is_xhr %> |
|
12 |
<%= submit_tag l(:button_save), :disable_with => l(:label_backup_in_progress) %> |
|
13 |
<%= link_to l(:button_cancel), url_for(:controller => 'repositories', :action => 'edit', :id => @repository.id) %> |
|
14 |
<% end %> |
|
15 |
<% end %> |
app/views/repository_protected_branches/form_error.js.erb | ||
---|---|---|
1 |
$('#validation_messages_protected_branch').html("<%= escape_javascript(error_messages_for 'protected_branch') %>"); |
app/views/repository_protected_branches/index.html.erb | ||
---|---|---|
1 |
<div> |
|
2 | ||
3 |
<% if user_allowed_to(:create_repository_protected_branches, @project) %> |
|
4 |
<div class="contextual"> |
|
5 |
<%= link_to(l(:label_protected_branch_add), new_repository_protected_branch_path(@repository), |
|
6 |
:class => 'icon icon-add modal-box') %> |
|
7 | ||
8 |
</div> |
|
9 |
<% end %> |
|
10 | ||
11 |
<h3><%= l(:label_protected_branches) %></h3> |
|
12 | ||
13 |
<% if @repository_protected_branches.any? %> |
|
14 | ||
15 |
<table id="protected_branches" class="table table-hover" data-update-url="<%= sort_repository_protected_branches_url %>"> |
|
16 |
<thead> |