Project

General

Profile

Patch #2525 » 0004-Redmine-management-of-Git-repositories.patch

Tomek Piotrowski, 2009-03-18 21:59

View differences:

app/controllers/my_controller.rb
48 48
    @blocks = @user.pref[:my_page_layout] || DEFAULT_LAYOUT
49 49
  end
50 50

  
51
  def remove_key
52
    if params[:id]
53
      AuthorizedKeysEntry.remove_entry_by_key(params[:id])
54
      redirect_to :action => 'account'
55
    end
56
  end
57

  
51 58
  # Edit user's account
52 59
  def account
53 60
    @user = User.current
......
57 64
      @user.mail_notification = (params[:notification_option] == 'all')
58 65
      @user.pref.attributes = params[:pref]
59 66
      @user.pref[:no_self_notified] = (params[:no_self_notified] == '1')
67
      if params[:new_key]
68
        begin
69
          key = AuthorizedKeysEntry.new(params[:new_key],@user.login)
70
          key.save
71
        rescue ArgumentError => e
72
          @user.errors.add('Key', e.message)
73
        end
74
      end
60 75
      if @user.save
61 76
        @user.pref.save
62 77
        @user.notified_project_ids = (params[:notification_option] == 'selected' ? params[:notified_project_ids] : [])
app/helpers/repositories_helper.rb
164 164
  end
165 165

  
166 166
  def git_field_tags(form, repository)
167
      content_tag('p', form.text_field(:url, :label => 'Path to .git directory', :size => 60, :required => true, :disabled => (repository && !repository.root_url.blank?)))
167
      if Setting.serve_git_repositories? and (repository == nil or repository.url.blank?)
168
          content_tag('p', form.text_field(:url, :value => GitManager.repositories_root + '/' + repository.project.identifier + '.git'), :label => 'Path to .git directory', :size => 60, :required => true)
169
      else
170
          content_tag('p', form.text_field(:url, :label => 'Path to .git directory', :size => 60, :required => true, :disabled => (repository && !repository.root_url.blank?)))
171
      end
168 172
  end
169 173

  
170 174
  def cvs_field_tags(form, repository)
app/models/authorized_keys_entry.rb
1
require "strscan"
2

  
3
class AuthorizedKeysEntry
4
  COMMENT=/^#/
5
  BLANK=/^\s+$/
6
  KEY_TYPES=['ssh-1','ssh-dss','ssh-rsa']
7
  # For ssh1 keys bits and exponent parts go into @key(key content) variable
8
  PARSERS = {'ssh-1' => /^(?:(.+) )?(\d+ \d+ [^ ]+)(?: (.+))$/, 
9
           'ssh-dss' => /^(?:(.+) )?ssh-dss ([^ ]+)(?: (.+))$/,
10
           'ssh-rsa' => /^(?:(.+) )?ssh-rsa ([^ ]+)(?: (.+))$/}
11
  KEY_DISPLAYNAMES={'ssh-1' => '', 'ssh-dss' => 'ssh-dss ', 'ssh-rsa' => 'ssh-rsa ' }
12

  
13
  KEY_FORMAT=/\A[\w\/\+\=]+\z/
14
  IDENTIFIER_FORMAT=/\A[\w@\.\-]+\z/
15
  @@authorized_keys_filename="~/.ssh/authorized_keys"
16

  
17
  attr_reader :identifier, :key, :key_type
18
  attr_accessor :options
19

  
20
  # Create object from string from authorized_keys
21
  def initialize(authorized_keys_string = nil,identifier = nil)
22
    @identifier = identifier if identifier
23
    @key = ''
24
    @options = []
25
    create_from_authorized_keys(authorized_keys_string) if authorized_keys_string != nil
26
  end
27

  
28
  def self.authorized_keys_filename=(filename)
29
    @@authorized_keys_filename=filename
30
  end
31

  
32
  def self.authorized_keys_filename
33
    @@authorized_keys_filename
34
  end
35

  
36
  def save
37
    @options = GitManager::get_authorized_keys_options_for_login(identifier)
38
    AuthorizedKeysEntry.add_entry(self)
39
  end
40

  
41
  def self.find_by_identifier(identifier)
42
    result = Array.new
43
    read_entries.each do |entry|
44
      result << entry if entry.identifier == identifier
45
    end
46
    return result
47
  end
48

  
49
  def to_s
50
    s = ""
51
    s += @options.join(",") + " " unless @options.empty?
52
    s += KEY_DISPLAYNAMES[@key_type] + @key
53
    s += " " + @identifier if @identifier
54
    return s
55
  end
56

  
57
  def self.remove_entry_by_key(key)
58
    entries = self.read_entries
59
    entries = entries.delete_if { |e| e.key[0,40] == key[0,40] }
60
    self.save_entries(entries)
61
  end
62

  
63
  def self.add_entry(entry)
64
    entries = self.read_entries
65
    entries << entry
66
    self.save_entries(entries)
67
  end
68

  
69
  private
70

  
71
  def get_key_type(line)
72
    KEY_TYPES.each do |k|
73
      return k if PARSERS[k].match(line)
74
    end
75
    return nil
76
  end
77

  
78
  def create_from_authorized_keys(line)
79
    @key_type = get_key_type(line)
80
    raise ArgumentError, "Invalid format of authorized_keys entry " + line if @key_type == nil
81
    m = PARSERS[@key_type].match(line)
82
    @options, @key = m[1], m[2]
83
    @identifier = m[3] unless @identifier
84
    @options = AuthorizedKeysEntry.parse_options(@options)
85
  end
86

  
87
  def self.parse_options(options)
88
    result = []
89
    return result if options == nil
90
    scanner = StringScanner.new(options)
91
    while !scanner.eos?
92
      scanner.skip(/[ \t]*/)
93
      # scan a long option
94
      if out = scanner.scan(/[-a-z0-9A-Z_]+=\".*?\"/) or out = scanner.scan(/[-a-z0-9A-Z_]+/)
95
        result << out
96
      else
97
        # found an unscannable token, let's abort
98
        break
99
      end
100
      # eat a comma
101
      scanner.skip(/[\t]*,[\t]*/)
102
    end
103
    return result
104
  end
105

  
106
  # Reads all entries from a file
107
  def self.read_entries
108
    entries = Array.new
109
    filename = File.expand_path(@@authorized_keys_filename)
110
    if !File.exists?(filename)
111
      return entries
112
    end
113

  
114
    File.open(filename) do |file|
115
      file.flock(File::LOCK_SH)
116
      begin
117
        file.each_line do |line|
118
          next if COMMENT.match(line) or BLANK.match(line)
119
          entries << AuthorizedKeysEntry.new(line)
120
        end
121
      ensure
122
        file.flock(File::LOCK_UN)
123
      end
124
    end 
125
    entries
126
  end
127

  
128
  # Saves all entries to a file
129
  def self.save_entries(entries)
130
    filename = File.expand_path(@@authorized_keys_filename)
131
    FileUtils.mkdir_p(File.dirname(filename))
132

  
133
    File.open(filename, "w") do |write_file|
134
      write_file.flock(File::LOCK_EX)
135
      entries.each do |entry|
136
        write_file << entry.to_s + "\n"
137
      end
138
      write_file.flock(File::LOCK_UN)
139
    end
140
  end
141
end
app/models/changeset.rb
70 70
    scan_comment_for_issue_ids
71 71
  end
72 72
  require 'pp'
73
  
74
  def scan_comment_for_issue_ids
75
    return if comments.blank?
73

  
74
  # returns issue ids found in message
75
  # three arrays are returned, references issues, fixed ones and wrong numbers (not Issues)
76
  def self.find_issue_ids(message, project)
77
    return [[],[]] if message.blank?
76 78
    # keywords used to reference issues
77 79
    ref_keywords = Setting.commit_ref_keywords.downcase.split(",").collect(&:strip)
78 80
    # keywords used to fix issues
79 81
    fix_keywords = Setting.commit_fix_keywords.downcase.split(",").collect(&:strip)
80
    # status and optional done ratio applied
81
    fix_status = IssueStatus.find_by_id(Setting.commit_fix_status_id)
82
    done_ratio = Setting.commit_fix_done_ratio.blank? ? nil : Setting.commit_fix_done_ratio.to_i
83 82
    
84 83
    kw_regexp = (ref_keywords + fix_keywords).collect{|kw| Regexp.escape(kw)}.join("|")
85
    return if kw_regexp.blank?
84
    return [[],[]] if kw_regexp.blank?
86 85
    
87 86
    referenced_issues = []
87
    fixed_issues = []
88
    wrong_issue_ids = []
88 89
    
89 90
    if ref_keywords.delete('*')
90 91
      # find any issue ID in the comments
91 92
      target_issue_ids = []
92
      comments.scan(%r{([\s\(,-]|^)#(\d+)(?=[[:punct:]]|\s|<|$)}).each { |m| target_issue_ids << m[1] }
93
      referenced_issues += repository.project.issues.find_all_by_id(target_issue_ids)
93
      message.scan(%r{([\s\(,-]|^)#(\d+)(?=[[:punct:]]|\s|<|$)}).each { |m| target_issue_ids << m[1] }
94
      found_issues = project.issues.find_all_by_id(target_issue_ids)
95
      referenced_issues += found_issues
96
      found_issues.each { |issue| target_issue_ids.delete(issue.id.to_s) }
97
      wrong_issue_ids += target_issue_ids
94 98
    end
95 99
    
96
    comments.scan(Regexp.new("(#{kw_regexp})[\s:]+(([\s,;&]*#?\\d+)+)", Regexp::IGNORECASE)).each do |match|
100
    message.scan(Regexp.new("(#{kw_regexp})[\s:]+(([\s,;&]*#?\\d+)+)", Regexp::IGNORECASE)).each do |match|
97 101
      action = match[0]
98 102
      target_issue_ids = match[1].scan(/\d+/)
99
      target_issues = repository.project.issues.find_all_by_id(target_issue_ids)
100
      if fix_status && fix_keywords.include?(action.downcase)
101
        # update status of issues
102
        logger.debug "Issues fixed by changeset #{self.revision}: #{issue_ids.join(', ')}." if logger && logger.debug?
103
        target_issues.each do |issue|
104
          # the issue may have been updated by the closure of another one (eg. duplicate)
105
          issue.reload
106
          # don't change the status is the issue is closed
107
          next if issue.status.is_closed?
108
          csettext = "r#{self.revision}"
109
          if self.scmid && (! (csettext =~ /^r[0-9]+$/))
110
            csettext = "commit:\"#{self.scmid}\""
111
          end
112
          journal = issue.init_journal(user || User.anonymous, l(:text_status_changed_by_changeset, csettext))
113
          issue.status = fix_status
114
          issue.done_ratio = done_ratio if done_ratio
115
          issue.save
116
          Mailer.deliver_issue_edit(journal) if Setting.notified_events.include?('issue_updated')
117
        end
103
      target_issues = project.issues.find_all_by_id(target_issue_ids)
104
      target_issues.each { |issue| target_issue_ids.delete(issue.id.to_s) }
105
      wrong_issue_ids += target_issue_ids
106
      if fix_keywords.include?(action.downcase)
107
        fixed_issues += target_issues
108
      else
109
        referenced_issues += target_issues
118 110
      end
119
      referenced_issues += target_issues
120 111
    end
121
    
122
    self.issues = referenced_issues.uniq
112
    return [referenced_issues.uniq, fixed_issues.uniq, wrong_issue_ids.uniq]
113
  end
114
  
115
  def scan_comment_for_issue_ids
116
    return if comments.blank?
117
    # status and optional done ratio applied
118
    fix_status = IssueStatus.find_by_id(Setting.commit_fix_status_id)
119
    done_ratio = Setting.commit_fix_done_ratio.blank? ? nil : Setting.commit_fix_done_ratio.to_i
120

  
121
    referenced_issues, fixed_issues, wrong_issues = Changeset.find_issue_ids(comments, repository.project)
122

  
123
    # update status of issues
124
    logger.debug "Issues fixed by changeset #{self.revision}: #{issue_ids.join(', ')}." if logger && logger.debug?
125
    fixed_issues.each do |issue|
126
      # the issue may have been updated by the closure of another one (eg. duplicate)
127
      issue.reload
128
      # don't change the status is the issue is closed
129
      next if issue.status.is_closed?
130
      csettext = "r#{self.revision}"
131
      if self.scmid && (! (csettext =~ /^r[0-9]+$/))
132
        csettext = "commit:\"#{self.scmid}\""
133
      end
134
      journal = issue.init_journal(user || User.anonymous, l(:text_status_changed_by_changeset, csettext))
135
      issue.status = fix_status
136
      issue.done_ratio = done_ratio if done_ratio
137
      issue.save
138
      Mailer.deliver_issue_edit(journal) if Setting.notified_events.include?('issue_updated')
139
    end
140
    self.issues = (referenced_issues + fixed_issues).uniq
123 141
  end
124 142
  
125 143
  # Returns the previous changeset
app/models/git_checks/committer.rb
1
class GitChecks::Committer < GitManager::CommitCheck
2
  def self.check(revision, branch, user, role, project, git)
3
    # Check: committer name and email
4
    if revision.author != "#{user.name} <#{user.mail}>"
5
      return [ "Commit author name or email is wrong",
6
	       "    Execute following commands and _recreate_ commit:",
7
               "    git config --global user.name \"#{user.name}\"",
8
	       "    git config --global user.email #{user.mail}",
9
      ]
10
    end
11
    return []
12
  end
13
end
14

  
app/models/git_checks/delete_branch.rb
1
class GitChecks::DeleteBranch < GitManager::RefCheck
2
  def self.check(old_rev, new_rev, new_rev_type, branch, user, role, project, git)
3
    if new_rev_type == "delete"
4
      return "Deleting branch can be done only by repository manager"
5
    end
6
    return []
7
  end
8
end
9

  
app/models/git_checks/fast_forward.rb
1
class GitChecks::FastForward < GitManager::RefCheck
2
  def self.check(old_rev, new_rev, new_rev_type, branch, user, role, project, git)
3
    # Check: fast forward
4
    if old_rev != git.class::EMPTY_COMMIT and git.merge_base(old_rev, new_rev) != old_rev
5
      return "Only fast-forward commits are allowed"
6
    end
7
    return []
8
  end
9
end
10

  
app/models/git_checks/initial_commit.rb
1
class GitChecks::InitialCommit < GitManager::RefCheck
2
  def self.check(old_rev, new_rev, new_rev_type, branch, user, role, project, git)
3
    if old_rev == git.class::EMPTY_COMMIT and !role.allowed_to?(:manage_repository)
4
      return "Initial commit can be done only by repository manager"
5
    end
6
    return []
7
  end
8
end
9

  
app/models/git_checks/issue.rb
1
class GitChecks::Issue < GitManager::CommitCheck
2
  def self.check(revision, branch, user, role, project, git)
3
    referenced_issues, fixes_issues, wrong_issues = Changeset.find_issue_ids(revision.message, project)
4
    issues = referenced_issues + fixes_issues
5

  
6
    errors = []
7

  
8
    if !wrong_issues.empty?
9
      errors << "Some issue numbers are wrong: #{wrong_issues.join(',')}"
10
    end
11

  
12
    issues.each do |issue_number|
13
      issue = Issue.find(issue_number)
14
      if issue.closed?
15
        errors << "Issue \##{issue.id} is closed. Reopen it and commit again"
16
      end
17
      if issue.assigned_to != user
18
        if issue.assigned_to != nil
19
          owner_info = "It belongs to #{issue.assigned_to.firstname} #{issue.assigned_to.lastname}"
20
        else
21
          owner_info = "It is unassigned"
22
        end
23
        errors << "Issue \##{issue.id} is not assigned to You. #{owner_info}"
24
      end
25
    end
26
    return errors
27
  end
28
end
29

  
app/models/git_manager.rb
1
require 'net/http'
2
require 'uri'
3
require 'redmine/scm/adapters/git_adapter'
4

  
5
class GitManager
6
  COMMANDS_READONLY = [
7
    'git-upload-pack',
8
  ]
9
  COMMANDS_WRITE = [
10
    'git-receive-pack',
11
  ]
12
  # TODO: make configurable
13
  REPOSITORIES_ROOT='~/repositories/'
14
  REDMINE_LOGIN_ENV_NAME='REDMINE_LOGIN'
15

  
16
  def self.repositories_root
17
    return File.expand_path(REPOSITORIES_ROOT)
18
  end
19

  
20
  
21
  # Executed by SSH when somebody logs into Redmine's SSH account
22
  # using public key.
23
  # Restricts the user to access only Git repositories he is allowed to.
24
  def self.serve
25
    begin
26
      command = serve_get_original_command
27
      user = serve_get_user
28
      git_command, project_identifier = parse_git_command(command)
29
      project, repository = find_project_and_repo(project_identifier)
30
      role = user.role_for_project(project)
31

  
32
      if COMMANDS_READONLY.include?(git_command)
33
        if !role.allowed_to?(:view_changesets)
34
          raise "User #{user} (#{role.name}) is not allowed to read project #{project}\n"
35
        end
36
        if !repository.scm.info
37
          raise "Empty repository. Push some commit first"
38
        end
39
      elsif COMMANDS_WRITE.include?(git_command)
40
        if !role.allowed_to?(:commit_access)
41
          raise "User #{user} (#{role.name}) is not allowed to write to project #{project}\n"
42
        end
43
        if !repository.scm.info
44
          warn "Creating new repository.\n"
45
          repository.scm.init(project.description)
46
        end
47
      else
48
        raise "Unknown command '#{verb}'"
49
      end
50
    
51
    rescue
52
      warn "Error: #{$!}.\n"
53
      exit 1
54
    end
55

  
56
    ENV[REDMINE_LOGIN_ENV_NAME]=user.login
57
    exec 'git', 'shell', '-c', "#{git_command} '#{repository.url}'"
58
  end
59

  
60
  def self.get_authorized_keys_options_for_login(login)
61
    return [ 'command="ruby ' + RAILS_ROOT + '/script/runner GitManager.serve \'' + login + '\' -e ' + ENV["RAILS_ENV"] +
62
	  '"', 'no-port-forwarding','no-X11-forwarding','no-agent-forwarding','no-pty' ]
63
  end
64

  
65

  
66
  private
67
  def self.serve_get_original_command
68
    command = ENV["SSH_ORIGINAL_COMMAND"]
69
    if command == nil or command==""
70
      raise "SSH_ORIGINAL_COMMAND not set. Use Git to access this account"
71
    end
72
    if command=~/\n/
73
      raise "Command contains new line character"
74
    end
75
    return command
76
  end
77

  
78
  def self.serve_get_user
79
    login = ARGV[0]
80
    if login == nil or login==""
81
      raise "Needs login as parameter"
82
    end
83
    user = User.find_by_login(login)
84
    if user == nil
85
      raise "User not found #{login}"
86
    end
87
    return user
88
  end
89

  
90
  def self.parse_git_command(command)
91
    verb, args = command.split(" ",2)
92
    if verb == 'git'
93
       subverb, args = args.split(" ",2)
94
       verb = "%s-%s" % [ verb, subverb ]
95
    end
96
    project_identifier = args.gsub("'","")
97
    return verb, project_identifier
98
  end
99

  
100
  def self.find_project_and_repo(project_identifier)
101
    project = Project.find_by_identifier(project_identifier)
102
    if project == nil
103
      raise "Project not found \"#{project_identifier}\""
104
    end
105

  
106
    repository = project.repository
107
    if repository == nil
108
      raise "Project #{project} does not have repository\n"
109
    end
110

  
111
    if repository.class != Repository::Git
112
      raise "Project #{project} has non git repository #{repository.type}"
113
    end
114
    return project, repository
115
  end
116

  
117

  
118
  public
119

  
120
  class RefCheck
121
    @@checks = []
122

  
123
    # Check Git ref, subclassess should override
124
    def check(old_rev, new_rev, new_rev_type, branch, user, role, project, git)
125
      return true
126
    end
127

  
128
    def self.inherited(subclass)
129
      @@checks << subclass
130
    end
131

  
132
    def self.get_checks
133
      return @@checks
134
    end
135
  end
136
  class CommitCheck
137
    @@checks = []
138

  
139
    # Check Git ref, subclassess should override
140
    def check(revision, branch, user, role, project, git)
141
      return true
142
    end
143

  
144
    def self.inherited(subclass)
145
      @@checks << subclass
146
    end
147

  
148
    def self.get_checks
149
      return @@checks
150
    end
151
  end
152

  
153
  def self.load_checks
154
    files = Dir.glob(RAILS_ROOT + "/app/models/git_checks/*.rb")
155
    files.each do |f|
156
      f.sub!(/\A#{RAILS_ROOT}/,'')
157
      f.split('/')[3..-1].join('/').split('.').first.camelize.constantize
158
    end
159
  end
160
  load_checks
161

  
162
  def self.check_commits
163
    login = ENV[REDMINE_LOGIN_ENV_NAME]
164
    if login == nil
165
      warn "Redmine: Local user, not running checks"
166
      exit 0
167
    end
168

  
169
    begin
170
      user = User.find_by_login(login)
171
      raise "User not found" if user == nil
172
      repository = Repository.find_by_url(Dir.getwd)
173
      raise "Repository not managed by Redmine" if repository == nil
174
      raise "Non git repository" if repository.class != Repository::Git
175
      project = repository.project
176
      role = user.role_for_project(project)
177
      git = repository.scm
178
      
179
      warn ""
180
      warn "-------------------------------------------------------------"
181
      warn "Redmine is checking your changes for correctness..."
182
      warn "Authenticated as #{user.name} (#{role.name} in #{project.name})"
183

  
184
      error_found = false
185

  
186
      warn "Changes:"
187
      STDIN.each_line do |line|
188
        old_rev, new_rev, branch = line.split(" ")
189
      
190
        if new_rev == git.class::EMPTY_COMMIT
191
          new_rev_type = "delete"
192
        else
193
          new_rev_type = git.get_object_type(new_rev)
194
        end
195
        revisions = nil
196
        if new_rev_type == "commit"
197
          revisions = git.revisions("", old_rev, new_rev)
198
        end
199
        warn "    Ref: #{branch} type: #{new_rev_type}"
200

  
201
	errors = []
202
	# TODO: make checks configurable
203
        RefCheck.get_checks.each do |check|
204
          result = check.check(old_rev, new_rev, new_rev_type, branch, user, role, project, git)
205
          if result.kind_of?(Array)
206
            errors += result
207
	  else
208
            errors << result
209
          end
210
        end
211
        errors.each do |error|
212
          warn "            Error: #{error}"
213
        end
214
	error_found = true if !errors.empty?
215

  
216
        if revisions != nil
217
	  revisions.each do |revision|
218
	    warn "        Commit: #{revision.identifier}"
219

  
220
	    errors = []
221
            CommitCheck.get_checks.each do |check|
222
              result = check.check(revision, branch, user, role, project, git)
223
              if result.kind_of?(Array)
224
                errors += result
225
	      else
226
                errors << result
227
              end
228
            end
229
            errors.each do |error|
230
              warn "            Error: #{error}"
231
            end
232
	    error_found = true if !errors.empty?
233
          end
234
        end
235
      end
236
    end
237
    
238
    if error_found
239
      if !role.allowed_to?(:manage_repository)
240
        warn "Some commits were rejected. Correct them and try the push again."
241
        warn "-------------------------------------------------------------"
242
	warn ""
243
        exit 1
244
      else
245
        warn "You are repository manager. Checks results are ignored. "
246
        warn "-------------------------------------------------------------"
247
	exit 0
248
      end
249
    end
250
    warn "Changes look OK"
251
    warn "-------------------------------------------------------------"
252
    exit 0
253
  end
254

  
255
end
256

  
app/models/user.rb
65 65
  validates_length_of :password, :minimum => 4, :allow_nil => true
66 66
  validates_confirmation_of :password, :allow_nil => true
67 67

  
68

  
69
  def ssh_key_entries
70
    AuthorizedKeysEntry.find_by_identifier(login)
71
  end
72

  
68 73
  def before_create
69 74
    self.mail_notification = false
70 75
    true
......
74 79
    # update hashed_password if password was set
75 80
    self.hashed_password = User.hash_password(self.password) if self.password
76 81
  end
82

  
77 83
  
78 84
  def reload(*args)
79 85
    @name = nil
......
271 277
  def self.hash_password(clear_password)
272 278
    Digest::SHA1.hexdigest(clear_password || "")
273 279
  end
280

  
274 281
end
275 282

  
276 283
class AnonymousUser < User
app/views/my/account.rhtml
15 15
<p><%= f.text_field :lastname, :required => true %></p>
16 16
<p><%= f.text_field :mail, :required => true %></p>
17 17
<p><%= f.select :language, lang_options_for_select %></p>
18
<% if Setting.serve_git_repositories? %>
19
  <table>
20
  <% @user.ssh_key_entries.each do |e| %>
21
    <tr><td><%= e.identifier + " " + e.key[0,30] %>... </td><td><%= link_to 'Remove', {:action => 'remove_key', :id =>  e.key[0,40]}, :confirm => "Are you sure?" %></td></tr>
22
  <% end %>
23
</table>
24
  <p><%= text_area_tag :new_key, '' %></p>
25
<% end %>
26

  
18 27
</div>
19 28

  
20 29
<%= submit_tag l(:button_save) %>
app/views/settings/_repositories.rhtml
14 14
<%= hidden_field_tag 'settings[enabled_scm][]', '' %>
15 15
</p>
16 16

  
17
<% # TODO: Should be disabled when Git SCM is not enabled 
18
%>
19
<p><label><%= l(:setting_serve_git_repositories) %></label>
20
<%= check_box_tag 'settings[serve_git_repositories]', 1, Setting.serve_git_repositories? %>
21
<%= hidden_field_tag 'settings[serve_git_repositories]', 0 %>
22
</p>
23

  
24

  
17 25
<p><label><%= l(:setting_repositories_encodings) %></label>
18 26
<%= text_field_tag 'settings[repositories_encodings]', Setting.repositories_encodings, :size => 60 %><br /><em><%= l(:text_comma_separated) %></em></p>
19 27

  
config/settings.yml
77 77
  default: 1
78 78
sys_api_enabled:
79 79
  default: 0
80
serve_git_repositories:
81
  default: 0
80 82
commit_ref_keywords:
81 83
  default: 'refs,references,IssueID'
82 84
commit_fix_keywords:
lang/bg.yml
92 92
field_firstname: Име
93 93
field_lastname: Фамилия
94 94
field_mail: Email
95
field_ssh_key: SSH Public Key
96
field_ssh_key_type: SSH Public Key Type
95 97
field_filename: Файл
96 98
field_filesize: Големина
97 99
field_downloads: Downloads
......
181 183
setting_feeds_limit: Лимит на Feeds
182 184
setting_autofetch_changesets: Автоматично обработване на ревизиите
183 185
setting_sys_api_enabled: Разрешаване на WS за управление
186
setting_serve_git_repositories: Serve GIT repositories using Redmine's SSH account
184 187
setting_commit_ref_keywords: Отбелязващи ключови думи
185 188
setting_commit_fix_keywords: Приключващи ключови думи
186 189
setting_autologin: Автоматичен вход
lang/ca.yml
106 106
field_firstname: Nom
107 107
field_lastname: Cognom
108 108
field_mail: Correu electrònic 
109
field_ssh_key: SSH Public Key
110
field_ssh_key_type: SSH Public Key Type
109 111
field_filename: Fitxer
110 112
field_filesize: Mida
111 113
field_downloads: Baixades
......
202 204
setting_default_projects_public: Els projectes nous són públics per defecte
203 205
setting_autofetch_changesets: Omple automàticament les publicacions
204 206
setting_sys_api_enabled: Habilita el WS per a la gestió del dipòsit
207
setting_serve_git_repositories: Serve GIT repositories using Redmine's SSH account
205 208
setting_commit_ref_keywords: Paraules claus per a la referència
206 209
setting_commit_fix_keywords: Paraules claus per a la correcció
207 210
setting_autologin: Entrada automàtica
lang/cs.yml
106 106
field_firstname: Jméno
107 107
field_lastname: Příjmení
108 108
field_mail: Email
109
field_ssh_key: SSH Public Key
110
field_ssh_key_type: SSH Public Key Type
109 111
field_filename: Soubor
110 112
field_filesize: Velikost
111 113
field_downloads: Staženo
......
201 203
setting_default_projects_public: Nové projekty nastavovat jako veřejné
202 204
setting_autofetch_changesets: Autofetch commits
203 205
setting_sys_api_enabled: Povolit WS pro správu repozitory
206
setting_serve_git_repositories: Serve GIT repositories using Redmine's SSH account
204 207
setting_commit_ref_keywords: Klíčová slova pro odkazy
205 208
setting_commit_fix_keywords: Klíčová slova pro uzavření
206 209
setting_autologin: Automatické přihlašování
lang/da.yml
106 106
field_firstname: Fornavn
107 107
field_lastname: Efternavn
108 108
field_mail: E-mail
109
field_ssh_key: SSH Public Key
110
field_ssh_key_type: SSH Public Key Type
109 111
field_filename: Fil
110 112
field_filesize: Størrelse
111 113
field_downloads: Downloads
......
204 206
setting_sys_api_enabled: Aktiver webservice til versionsstyring
205 207
setting_commit_ref_keywords: Nøgleord for sagsreferencer
206 208
setting_commit_fix_keywords: Nøgleord for lukning af sager
209
setting_serve_git_repositories: Serve GIT repositories using Redmine's SSH account
207 210
setting_autologin: Autologin
208 211
setting_date_format: Datoformat
209 212
setting_time_format: Tidsformat
lang/de.yml
106 106
field_firstname: Vorname
107 107
field_lastname: Nachname
108 108
field_mail: E-Mail
109
field_ssh_key: SSH Public Key
110
field_ssh_key_type: SSH Public Key Type
109 111
field_filename: Datei
110 112
field_filesize: Größe
111 113
field_downloads: Downloads
......
203 205
setting_default_projects_public: Neue Projekte sind standardmäßig öffentlich
204 206
setting_autofetch_changesets: Changesets automatisch abrufen
205 207
setting_sys_api_enabled: Webservice zur Verwaltung der Projektarchive benutzen
208
setting_serve_git_repositories: Serve GIT repositories using Redmine's SSH account
206 209
setting_commit_ref_keywords: Schlüsselwörter (Beziehungen)
207 210
setting_commit_fix_keywords: Schlüsselwörter (Status)
208 211
setting_autologin: Automatische Anmeldung
lang/en.yml
108 108
field_firstname: Firstname
109 109
field_lastname: Lastname
110 110
field_mail: Email
111
field_new_key: SSH Public Key
111 112
field_filename: File
112 113
field_filesize: Size
113 114
field_downloads: Downloads
......
205 206
setting_default_projects_public: New projects are public by default
206 207
setting_autofetch_changesets: Autofetch commits
207 208
setting_sys_api_enabled: Enable WS for repository management
209
setting_serve_git_repositories: Serve GIT repositories using Redmine's SSH account
208 210
setting_commit_ref_keywords: Referencing keywords
209 211
setting_commit_fix_keywords: Fixing keywords
210 212
setting_autologin: Autologin
lang/es.yml
150 150
field_lastname: Apellido
151 151
field_login: Identificador
152 152
field_mail: Correo electrónico
153
field_ssh_key: SSH Public Key
154
field_ssh_key_type: SSH Public Key Type
153 155
field_mail_notification: Notificaciones por correo
154 156
field_max_length: Longitud máxima
155 157
field_min_length: Longitud mínima
......
627 629
setting_self_registration: Registro permitido
628 630
setting_sequential_project_identifiers: Generar identificadores de proyecto
629 631
setting_sys_api_enabled: Habilitar SW para la gestión del repositorio
632
setting_serve_git_repositories: Serve GIT repositories using Redmine's SSH account
630 633
setting_text_formatting: Formato de texto
631 634
setting_time_format: Formato de hora
632 635
setting_user_format: Formato de nombre de usuario
lang/fi.yml
101 101
field_firstname: Etunimi
102 102
field_lastname: Sukunimi
103 103
field_mail: Sähköposti
104
field_ssh_key: SSH Public Key
105
field_ssh_key_type: SSH Public Key Type
104 106
field_filename: Tiedosto
105 107
field_filesize: Koko
106 108
field_downloads: Latausta
......
194 196
setting_feeds_limit: Syötteen sisällön raja
195 197
setting_autofetch_changesets: Automaattisten muutosjoukkojen haku
196 198
setting_sys_api_enabled: Salli WS tietovaraston hallintaan
199
setting_serve_git_repositories: Serve GIT repositories using Redmine's SSH account
197 200
setting_commit_ref_keywords: Viittaavat hakusanat
198 201
setting_commit_fix_keywords: Korjaavat hakusanat
199 202
setting_autologin: Automaatinen kirjautuminen
lang/fr.yml
108 108
field_firstname: Prénom
109 109
field_lastname: Nom
110 110
field_mail: Email
111
field_ssh_key: SSH Public Key
112
field_ssh_key_type: SSH Public Key Type
111 113
field_filename: Fichier
112 114
field_filesize: Taille
113 115
field_downloads: Téléchargements
......
205 207
setting_default_projects_public: Définir les nouveaux projects comme publics par défaut
206 208
setting_autofetch_changesets: Récupération auto. des commits
207 209
setting_sys_api_enabled: Activer les WS pour la gestion des dépôts
210
setting_serve_git_repositories: Serve GIT repositories using Redmine's SSH account
208 211
setting_commit_ref_keywords: Mot-clés de référencement
209 212
setting_commit_fix_keywords: Mot-clés de résolution
210 213
setting_autologin: Autologin
lang/he.yml
94 94
field_firstname: שם פרטי
95 95
field_lastname: שם משפחה
96 96
field_mail: דוא"ל
97
field_ssh_key: SSH Public Key
98
field_ssh_key_type: SSH Public Key Type
97 99
field_filename: קובץ
98 100
field_filesize: גודל
99 101
field_downloads: הורדות
......
184 186
setting_feeds_limit: גבול תוכן הזנות
185 187
setting_autofetch_changesets: משיכה אוטומתי של עידכונים
186 188
setting_sys_api_enabled: אפשר WS לניהול המאגר
189
setting_serve_git_repositories: Serve GIT repositories using Redmine's SSH account
187 190
setting_commit_ref_keywords: מילות מפתח מקשרות
188 191
setting_commit_fix_keywords: מילות מפתח מתקנות
189 192
setting_autologin: חיבור אוטומטי
lang/hu.yml
103 103
field_firstname: Keresztnév
104 104
field_lastname: Vezetéknév
105 105
field_mail: E-mail
106
field_ssh_key: SSH Public Key
107
field_ssh_key_type: SSH Public Key Type
106 108
field_filename: Fájl
107 109
field_filesize: Méret
108 110
field_downloads: Letöltések
......
198 200
setting_default_projects_public: Az új projektek alapértelmezés szerint nyilvánosak
199 201
setting_autofetch_changesets: Commitok automatikus lehúzása
200 202
setting_sys_api_enabled: WS engedélyezése a tárolók kezeléséhez
203
setting_serve_git_repositories: Serve GIT repositories using Redmine's SSH account
201 204
setting_commit_ref_keywords: Hivatkozó kulcsszavak
202 205
setting_commit_fix_keywords: Javítások kulcsszavai
203 206
setting_autologin: Automatikus bejelentkezés
lang/it.yml
92 92
field_firstname: Nome
93 93
field_lastname: Cognome
94 94
field_mail: Email
95
field_ssh_key: SSH Public Key
96
field_ssh_key_type: SSH Public Key Type
95 97
field_filename: File
96 98
field_filesize: Dimensione
97 99
field_downloads: Download
......
181 183
setting_feeds_limit: Limite contenuti del feed
182 184
setting_autofetch_changesets: Acquisisci automaticamente le commit
183 185
setting_sys_api_enabled: Abilita WS per la gestione del repository
186
setting_serve_git_repositories: Serve GIT repositories using Redmine's SSH account
184 187
setting_commit_ref_keywords: Referencing keywords
185 188
setting_commit_fix_keywords: Fixing keywords
186 189
setting_autologin: Login automatico
lang/ja.yml
93 93
field_firstname: 名前
94 94
field_lastname: 苗字
95 95
field_mail: メールアドレス
96
field_ssh_key: SSH Public Key
97
field_ssh_key_type: SSH Public Key Type
96 98
field_filename: ファイル
97 99
field_filesize: サイズ
98 100
field_downloads: ダウンロード
......
182 184
setting_feeds_limit: フィード内容の上限
183 185
setting_autofetch_changesets: コミットを自動取得する
184 186
setting_sys_api_enabled: リポジトリ管理用のWeb Serviceを有効にする
187
setting_serve_git_repositories: Serve GIT repositories using Redmine's SSH account
185 188
setting_commit_ref_keywords: 参照用キーワード
186 189
setting_commit_fix_keywords: 修正用キーワード
187 190
setting_autologin: 自動ログイン
lang/ko.yml
94 94
field_firstname: 이름
95 95
field_lastname: 성
96 96
field_mail: 메일
97
field_ssh_key: SSH Public Key
98
field_ssh_key_type: SSH Public Key Type
97 99
field_filename: 파일
98 100
field_filesize: 크기
99 101
field_downloads: 다운로드
......
184 186
setting_feeds_limit: 내용 피드(RSS Feed) 제한 개수
185 187
setting_autofetch_changesets: 커밋된 변경묶음을 자동으로 가져오기
186 188
setting_sys_api_enabled: 저장소 관리자에 WS 를 허용
189
setting_serve_git_repositories: Serve GIT repositories using Redmine's SSH account
187 190
setting_commit_ref_keywords: 일감 참조에 사용할 키워드들
188 191
setting_commit_fix_keywords: 일감 해결에 사용할 키워드들 
189 192
setting_autologin: 자동 로그인
lang/lt.yml
106 106
field_firstname: Vardas
107 107
field_lastname: Pavardė
108 108
field_mail: Email
109
field_ssh_key: SSH Public Key
110
field_ssh_key_type: SSH Public Key Type
109 111
field_filename: Byla
110 112
field_filesize: Dydis
111 113
field_downloads: Atsiuntimai
......
203 205
setting_default_projects_public: Naujas projektas viešas pagal nutylėjimą
204 206
setting_autofetch_changesets: Automatinis pakeitimų siuntimas
205 207
setting_sys_api_enabled: Įgalinkite WS sandėlio vadybai
208
setting_serve_git_repositories: Serve GIT repositories using Redmine's SSH account
206 209
setting_commit_ref_keywords: Nurodymo reikšminiai žodžiai
207 210
setting_commit_fix_keywords: Fiksavimo reikšminiai žodžiai
208 211
setting_autologin: Autoregistracija
lang/nl.yml
148 148
field_onthefly: On-the-fly aanmaken van een gebruiker
149 149
field_start_date: Start
150 150
field_done_ratio: %% Gereed
151
field_ssh_key: SSH Public Key
152
field_ssh_key_type: SSH Public Key Type
151 153
field_auth_source: Authenticatiemethode
152 154
field_hide_mail: Verberg mijn e-mailadres
153 155
field_comments: Commentaar
......
638 640
label_issue_watchers: Monitoren
639 641
setting_commit_logs_encoding: Encodering van commit berichten
640 642
button_quote: Citaat
643
setting_serve_git_repositories: Serve GIT repositories using Redmine's SSH account
641 644
setting_sequential_project_identifiers: Genereer sequentiële projectidentiteiten
642 645
notice_unable_delete_version: Niet mogelijk om deze versie te verwijderen.
643 646
label_renamed: hernoemd
lang/no.yml
105 105
field_firstname: Fornavn
106 106
field_lastname: Etternavn
107 107
field_mail: E-post
108
field_ssh_key: SSH Public Key
109
field_ssh_key_type: SSH Public Key Type
108 110
field_filename: Fil
109 111
field_filesize: Størrelse
110 112
field_downloads: Nedlastinger
......
200 202
setting_default_projects_public: Nye prosjekter er offentlige som standard
201 203
setting_autofetch_changesets: Autohenting av innsendinger
202 204
setting_sys_api_enabled: Aktiver webservice for depot-administrasjon
205
setting_serve_git_repositories: Serve GIT repositories using Redmine's SSH account
203 206
setting_commit_ref_keywords: Nøkkelord for referanse
204 207
setting_commit_fix_keywords: Nøkkelord for retting
205 208
setting_autologin: Autoinnlogging
lang/pl.yml
161 161
field_lastname: Nazwisko
162 162
field_login: Login
163 163
field_mail: Email
164
field_ssh_key: Klucz publiczny SSH
165
field_ssh_key_type: Typ klucza SSH
164 166
field_mail_notification: Powiadomienia Email
165 167
field_max_length: Maksymalna długość
166 168
field_min_length: Minimalna długość
......
657 659
setting_self_registration: Własna rejestracja umożliwiona
658 660
setting_sequential_project_identifiers: Generuj sekwencyjne identyfikatory projektów
659 661
setting_sys_api_enabled: Włączenie WS do zarządzania repozytorium
662
setting_serve_git_repositories: Udostępnij repozytoria GIT poprzez konto SSH Redmine
660 663
setting_text_formatting: Formatowanie tekstu
661 664
setting_time_format: Format czasu
662 665
setting_user_format: Personalny format wyświetlania
lang/pt-br.yml
105 105
field_firstname: Nome
106 106
field_lastname: Sobrenome
107 107
field_mail: Email
108
field_ssh_key: SSH Public Key
109
field_ssh_key_type: SSH Public Key Type
108 110
field_filename: Arquivo
109 111
field_filesize: Tamanho
110 112
field_downloads: Downloads
......
201 203
setting_default_projects_public: Novos projetos são públicos por padrão
202 204
setting_autofetch_changesets: Auto-obter commits
203 205
setting_sys_api_enabled: Ativa WS para gerenciamento do repositório
206
setting_serve_git_repositories: Serve GIT repositories using Redmine's SSH account
204 207
setting_commit_ref_keywords: Palavras de referência
205 208
setting_commit_fix_keywords: Palavras de fechamento
206 209
setting_autologin: Auto-login
lang/pt.yml
107 107
field_firstname: Nome
108 108
field_lastname: Apelido
109 109
field_mail: E-mail
110
field_ssh_key: SSH Public Key
111
field_ssh_key_type: SSH Public Key Type
110 112
field_filename: Ficheiro
111 113
field_filesize: Tamanho
112 114
field_downloads: Downloads
......
203 205
setting_default_projects_public: Projectos novos são públicos por omissão
204 206
setting_autofetch_changesets: Buscar automaticamente commits
205 207
setting_sys_api_enabled: Activar Web Service para gestão do repositório
208
setting_serve_git_repositories: Serve GIT repositories using Redmine's SSH account
206 209
setting_commit_ref_keywords: Palavras-chave de referência
207 210
setting_commit_fix_keywords: Palavras-chave de fecho
208 211
setting_autologin: Login automático
lang/ro.yml
92 92
field_firstname: Nume
93 93
field_lastname: Prenume
94 94
field_mail: Email
95
field_ssh_key: SSH Public Key
96
field_ssh_key_type: SSH Public Key Type
95 97
field_filename: Fisier
96 98
field_filesize: Marimea fisierului
97 99
field_downloads: Download
......
181 183
setting_feeds_limit: Limita continut feed
182 184
setting_autofetch_changesets: Autofetch commits
183 185
setting_sys_api_enabled: Setare WS pentru managementul stocului (repository)
186
setting_serve_git_repositories: Serve GIT repositories using Redmine's SSH account
184 187
setting_commit_ref_keywords: Cuvinte cheie de referinta
185 188
setting_commit_fix_keywords: Cuvinte cheie de rezolvare
186 189
setting_autologin: Autentificare automata
lang/ru.yml
165 165
field_lastname: Фамилия
166 166
field_login: Пользователь
167 167
field_mail: Email
168
field_ssh_key: SSH Public Key
169
field_ssh_key_type: SSH Public Key Type
168 170
field_mail_notification: Уведомления по email
169 171
field_max_length: Максимальная длина
170 172
field_min_length: Минимальная длина
......
673 675
setting_self_registration: Возможна саморегистрация
674 676
setting_sequential_project_identifiers: Генерировать последовательные идентификаторы проектов
675 677
setting_sys_api_enabled: Разрешить WS для управления хранилищем
678
setting_serve_git_repositories: Serve GIT repositories using Redmine's SSH account
676 679
setting_text_formatting: Форматирование текста
677 680
setting_time_format: Формат времени
678 681
setting_user_format: Формат отображения имени
lang/sk.yml
106 106
field_firstname: Meno
107 107
field_lastname: Priezvisko
108 108
field_mail: Email
109
field_ssh_key: SSH Public Key
110
field_ssh_key_type: SSH Public Key Type
109 111
field_filename: Súbor
110 112
field_filesize: Veľkosť
111 113
field_downloads: Stiahnuté
......
201 203
setting_default_projects_public: Nové projekty nastavovať ako verejné
202 204
setting_autofetch_changesets: Automatický prenos zmien
203 205
setting_sys_api_enabled: Povolit WS pre správu repozitory
206
setting_serve_git_repositories: Serve GIT repositories using Redmine's SSH account
204 207
setting_commit_ref_keywords: Klúčové slová pre odkazy
205 208
setting_commit_fix_keywords: Klúčové slová pre uzavretie
206 209
setting_autologin: Automatické prihlasovanie
......
698 701
permission_edit_own_messages: Edit own messages
699 702
permission_delete_own_messages: Delete own messages
700 703
text_repository_usernames_mapping: "Select or update the Redmine user mapped to each username found in the repository log.\nUsers with the same Redmine and repository username or email are automatically mapped."
701
label_user_activity: "%s's activity"
702
label_updated_time_by: Updated by %s %s ago
703
text_diff_truncated: '... This diff was truncated because it exceeds the maximum size that can be displayed.'
704
setting_diff_max_lines_displayed: Max number of diff lines displayed
705
text_plugin_assets_writable: Plugin assets directory writable
706
warning_attachments_not_saved: "%d file(s) could not be saved."
707
button_create_and_continue: Create and continue
704
label_user_activity: "%s's activity"
705
label_updated_time_by: Updated by %s %s ago
706
text_diff_truncated: '... This diff was truncated because it exceeds the maximum size that can be displayed.'
707
setting_diff_max_lines_displayed: Max number of diff lines displayed
708
text_plugin_assets_writable: Plugin assets directory writable
709
warning_attachments_not_saved: "%d file(s) could not be saved."
710
button_create_and_continue: Create and continue
lang/sr.yml
96 96
field_firstname: Ime
97 97
field_lastname: Prezime
98 98
field_mail: Email
99
field_ssh_key: SSH Public Key
100
field_ssh_key_type: SSH Public Key Type
99 101
field_filename: Fajl
100 102
field_filesize: Veličina
101 103
field_downloads: Preuzimanja
......
186 188
setting_feeds_limit: Feed content limit
187 189
setting_autofetch_changesets: Autofetch commits
188 190
setting_sys_api_enabled: Ukljuci WS za menadžment spremišta
191
setting_serve_git_repositories: Serve GIT repositories using Redmine's SSH account
189 192
setting_commit_ref_keywords: Referentne ključne reči
190 193
setting_commit_fix_keywords: Fiksne ključne reči
191 194
setting_autologin: Automatsko prijavljivanje
lang/sv.yml
106 106
field_firstname: Förnamn
107 107
field_lastname: Efternamn
108 108
field_mail: Mail
109
field_ssh_key: SSH Public Key
110
field_ssh_key_type: SSH Public Key Type
109 111
field_filename: Fil
110 112
field_filesize: Storlek
111 113
field_downloads: Nerladdningar
......
203 205
setting_default_projects_public: Nya projekt är publika som standard
204 206
setting_autofetch_changesets: Automatisk hämtning av commits
205 207
setting_sys_api_enabled: Aktivera WS för repository-hantering
208
setting_serve_git_repositories: Serve GIT repositories using Redmine's SSH account
206 209
setting_commit_ref_keywords: Referens-nyckelord
207 210
setting_commit_fix_keywords: Fix-nyckelord
208 211
setting_autologin: Automatisk inloggning
lang/th.yml
103 103
field_firstname: ชื่อ
104 104
field_lastname: นามสกุล
105 105
field_mail: อีเมล์
106
field_ssh_key: SSH Public Key
107
field_ssh_key_type: SSH Public Key Type
106 108
field_filename: แฟ้ม
107 109
field_filesize: ขนาด
108 110
field_downloads: ดาวน์โหลด
......
198 200
setting_default_projects_public: โครงการใหม่มีค่าเริ่มต้นเป็น สาธารณะ
199 201
setting_autofetch_changesets: ดึง commits อัตโนมัติ
200 202
setting_sys_api_enabled: เปิดใช้ WS สำหรับการจัดการที่เก็บต้นฉบับ
203
setting_serve_git_repositories: Serve GIT repositories using Redmine's SSH account
201 204
setting_commit_ref_keywords: คำสำคัญ Referencing
202 205
setting_commit_fix_keywords: คำสำคัญ Fixing
203 206
setting_autologin: เข้าระบบอัตโนมัติ
lang/tr.yml
102 102
field_firstname: Ad
103 103
field_lastname: Soyad
104 104
field_mail: E-Posta
105
field_ssh_key: SSH Public Key
106
field_ssh_key_type: SSH Public Key Type
105 107
field_filename: Dosya
106 108
field_filesize: Boyut
107 109
field_downloads: İndirilenler
......
197 199
setting_default_projects_public: Yeni projeler varsayılan olarak herkese açık
198 200
setting_autofetch_changesets: Otomatik gönderi al
199 201
setting_sys_api_enabled: Depo yönetimi için WS'yi etkinleştir
202
setting_serve_git_repositories: Serve GIT repositories using Redmine's SSH account
200 203
setting_commit_ref_keywords: Başvuru Kelimeleri
201 204
setting_commit_fix_keywords: Sabitleme kelimeleri
202 205
setting_autologin: Otomatik Giriş
lang/uk.yml
97 97
field_firstname: Ім'я
98 98
field_lastname: Прізвище
99 99
field_mail: Ел. пошта
100
field_ssh_key: SSH Public Key
101
field_ssh_key_type: SSH Public Key Type
100 102
field_filename: Файл
101 103
field_filesize: Розмір
102 104
field_downloads: Завантаження
......
189 191
setting_feeds_limit: Обмеження змісту подачі
190 192
setting_autofetch_changesets: Автоматично доставати доповнення
191 193
setting_sys_api_enabled: Дозволити WS для управління репозиторієм
194
setting_serve_git_repositories: Serve GIT repositories using Redmine's SSH account
192 195
setting_commit_ref_keywords: Ключові слова для посилання
193 196
setting_commit_fix_keywords: Призначення ключових слів
194 197
setting_autologin: Автоматичний вхід
lang/vn.yml
106 106
field_firstname: Tên lót + Tên
107 107
field_lastname: Họ
108 108
field_mail: Email
109
field_ssh_key: SSH Public Key
110
field_ssh_key_type: SSH Public Key Type
109 111
field_filename: Tập tin
110 112
field_filesize: Cỡ
111 113
field_downloads: Tải về
......
202 204
setting_default_projects_public: Dự án mặc định là công cộng
203 205
setting_autofetch_changesets: Autofetch commits
204 206
setting_sys_api_enabled: Enable WS for repository management
207
setting_serve_git_repositories: Serve GIT repositories using Redmine's SSH account
205 208
setting_commit_ref_keywords: Từ khóa tham khảo
206 209
setting_commit_fix_keywords: Từ khóa chỉ vấn đề đã giải quyết
207 210
setting_autologin: Tự động đăng nhập
lang/zh-tw.yml
106 106
field_firstname: 名字
107 107
field_lastname: 姓氏
108 108
field_mail: 電子郵件
109
field_ssh_key: SSH Public Key
110
field_ssh_key_type: SSH Public Key Type
109 111
field_filename: 檔案名稱
110 112
field_filesize: 大小
111 113
field_downloads: 下載次數
......
203 205
setting_autofetch_changesets: 自動取得送交版次
204 206
setting_default_projects_public: 新建立之專案預設為「公開」
205 207
setting_sys_api_enabled: 啟用管理版本庫之網頁服務 (Web Service)
208
setting_serve_git_repositories: Serve GIT repositories using Redmine's SSH account
206 209
setting_commit_ref_keywords: 送交用於參照項目之關鍵字
207 210
setting_commit_fix_keywords: 送交用於修正項目之關鍵字
208 211
setting_autologin: 自動登入
lang/zh.yml
106 106
field_firstname: 名字
107 107
field_lastname: 姓氏
108 108
field_mail: 邮件地址
109
field_ssh_key: SSH Public Key
110
field_ssh_key_type: SSH Public Key Type
109 111
field_filename: 文件
110 112
field_filesize: 大小
111 113
field_downloads: 下载次数
......
203 205
setting_default_projects_public: 新建项目默认为公开项目
204 206
setting_autofetch_changesets: 自动获取程序变更
205 207
setting_sys_api_enabled: 启用用于版本库管理的Web Service
208
setting_serve_git_repositories: Serve GIT repositories using Redmine's SSH account
206 209
setting_commit_ref_keywords: 用于引用问题的关键字
207 210
setting_commit_fix_keywords: 用于解决问题的关键字
208 211
setting_autologin: 自动登录
lib/redmine/scm/adapters/git_adapter.rb
24 24
        
... This diff was truncated because it exceeds the maximum size that can be displayed.
(5-5/5)