Actualiza a Redmine 3.4.13

This commit is contained in:
Manuel Cillero 2020-07-03 21:39:03 +02:00
parent 807ff3308d
commit ecddcaf1d3
224 changed files with 2222 additions and 1000 deletions

View file

@ -1,182 +1,182 @@
require 'rubygems'
Gem::manage_gems
require 'rake/rdoctask'
require 'rake/packagetask'
require 'rake/gempackagetask'
require 'rake/testtask'
require 'rake/contrib/rubyforgepublisher'
PKG_NAME = 'acts_as_versioned'
PKG_VERSION = '0.3.1'
PKG_FILE_NAME = "#{PKG_NAME}-#{PKG_VERSION}"
PROD_HOST = "technoweenie@bidwell.textdrive.com"
RUBY_FORGE_PROJECT = 'ar-versioned'
RUBY_FORGE_USER = 'technoweenie'
desc 'Default: run unit tests.'
task :default => :test
desc 'Test the calculations plugin.'
Rake::TestTask.new(:test) do |t|
t.libs << 'lib'
t.pattern = 'test/**/*_test.rb'
t.verbose = true
end
desc 'Generate documentation for the calculations plugin.'
Rake::RDocTask.new(:rdoc) do |rdoc|
rdoc.rdoc_dir = 'rdoc'
rdoc.title = "#{PKG_NAME} -- Simple versioning with active record models"
rdoc.options << '--line-numbers --inline-source'
rdoc.rdoc_files.include('README', 'CHANGELOG', 'RUNNING_UNIT_TESTS')
rdoc.rdoc_files.include('lib/**/*.rb')
end
spec = Gem::Specification.new do |s|
s.name = PKG_NAME
s.version = PKG_VERSION
s.platform = Gem::Platform::RUBY
s.summary = "Simple versioning with active record models"
s.files = FileList["{lib,test}/**/*"].to_a + %w(README MIT-LICENSE CHANGELOG RUNNING_UNIT_TESTS)
s.files.delete "acts_as_versioned_plugin.sqlite.db"
s.files.delete "acts_as_versioned_plugin.sqlite3.db"
s.files.delete "test/debug.log"
s.require_path = 'lib'
s.autorequire = 'acts_as_versioned'
s.has_rdoc = true
s.test_files = Dir['test/**/*_test.rb']
s.add_dependency 'activerecord', '>= 1.10.1'
s.add_dependency 'activesupport', '>= 1.1.1'
s.author = "Rick Olson"
s.email = "technoweenie@gmail.com"
s.homepage = "http://techno-weenie.net"
end
Rake::GemPackageTask.new(spec) do |pkg|
pkg.need_tar = true
end
desc "Publish the API documentation"
task :pdoc => [:rdoc] do
Rake::RubyForgePublisher.new(RUBY_FORGE_PROJECT, RUBY_FORGE_USER).upload
end
desc 'Publish the gem and API docs'
task :publish => [:pdoc, :rubyforge_upload]
desc "Publish the release files to RubyForge."
task :rubyforge_upload => :package do
files = %w(gem tgz).map { |ext| "pkg/#{PKG_FILE_NAME}.#{ext}" }
if RUBY_FORGE_PROJECT then
require 'net/http'
require 'open-uri'
project_uri = "http://rubyforge.org/projects/#{RUBY_FORGE_PROJECT}/"
project_data = open(project_uri) { |data| data.read }
group_id = project_data[/[?&]group_id=(\d+)/, 1]
raise "Couldn't get group id" unless group_id
# This echos password to shell which is a bit sucky
if ENV["RUBY_FORGE_PASSWORD"]
password = ENV["RUBY_FORGE_PASSWORD"]
else
print "#{RUBY_FORGE_USER}@rubyforge.org's password: "
password = STDIN.gets.chomp
end
login_response = Net::HTTP.start("rubyforge.org", 80) do |http|
data = [
"login=1",
"form_loginname=#{RUBY_FORGE_USER}",
"form_pw=#{password}"
].join("&")
http.post("/account/login.php", data)
end
cookie = login_response["set-cookie"]
raise "Login failed" unless cookie
headers = { "Cookie" => cookie }
release_uri = "http://rubyforge.org/frs/admin/?group_id=#{group_id}"
release_data = open(release_uri, headers) { |data| data.read }
package_id = release_data[/[?&]package_id=(\d+)/, 1]
raise "Couldn't get package id" unless package_id
first_file = true
release_id = ""
files.each do |filename|
basename = File.basename(filename)
file_ext = File.extname(filename)
file_data = File.open(filename, "rb") { |file| file.read }
puts "Releasing #{basename}..."
release_response = Net::HTTP.start("rubyforge.org", 80) do |http|
release_date = Time.now.strftime("%Y-%m-%d %H:%M")
type_map = {
".zip" => "3000",
".tgz" => "3110",
".gz" => "3110",
".gem" => "1400"
}; type_map.default = "9999"
type = type_map[file_ext]
boundary = "rubyqMY6QN9bp6e4kS21H4y0zxcvoor"
query_hash = if first_file then
{
"group_id" => group_id,
"package_id" => package_id,
"release_name" => PKG_FILE_NAME,
"release_date" => release_date,
"type_id" => type,
"processor_id" => "8000", # Any
"release_notes" => "",
"release_changes" => "",
"preformatted" => "1",
"submit" => "1"
}
else
{
"group_id" => group_id,
"release_id" => release_id,
"package_id" => package_id,
"step2" => "1",
"type_id" => type,
"processor_id" => "8000", # Any
"submit" => "Add This File"
}
end
query = "?" + query_hash.map do |(name, value)|
[name, URI.encode(value)].join("=")
end.join("&")
data = [
"--" + boundary,
"Content-Disposition: form-data; name=\"userfile\"; filename=\"#{basename}\"",
"Content-Type: application/octet-stream",
"Content-Transfer-Encoding: binary",
"", file_data, ""
].join("\x0D\x0A")
release_headers = headers.merge(
"Content-Type" => "multipart/form-data; boundary=#{boundary}"
)
target = first_file ? "/frs/admin/qrs.php" : "/frs/admin/editrelease.php"
http.post(target + query, data, release_headers)
end
if first_file then
release_id = release_response.body[/release_id=(\d+)/, 1]
raise("Couldn't get release id") unless release_id
end
first_file = false
end
end
require 'rubygems'
Gem::manage_gems
require 'rake/rdoctask'
require 'rake/packagetask'
require 'rake/gempackagetask'
require 'rake/testtask'
require 'rake/contrib/rubyforgepublisher'
PKG_NAME = 'acts_as_versioned'
PKG_VERSION = '0.3.1'
PKG_FILE_NAME = "#{PKG_NAME}-#{PKG_VERSION}"
PROD_HOST = "technoweenie@bidwell.textdrive.com"
RUBY_FORGE_PROJECT = 'ar-versioned'
RUBY_FORGE_USER = 'technoweenie'
desc 'Default: run unit tests.'
task :default => :test
desc 'Test the calculations plugin.'
Rake::TestTask.new(:test) do |t|
t.libs << 'lib'
t.pattern = 'test/**/*_test.rb'
t.verbose = true
end
desc 'Generate documentation for the calculations plugin.'
Rake::RDocTask.new(:rdoc) do |rdoc|
rdoc.rdoc_dir = 'rdoc'
rdoc.title = "#{PKG_NAME} -- Simple versioning with active record models"
rdoc.options << '--line-numbers --inline-source'
rdoc.rdoc_files.include('README', 'CHANGELOG', 'RUNNING_UNIT_TESTS')
rdoc.rdoc_files.include('lib/**/*.rb')
end
spec = Gem::Specification.new do |s|
s.name = PKG_NAME
s.version = PKG_VERSION
s.platform = Gem::Platform::RUBY
s.summary = "Simple versioning with active record models"
s.files = FileList["{lib,test}/**/*"].to_a + %w(README MIT-LICENSE CHANGELOG RUNNING_UNIT_TESTS)
s.files.delete "acts_as_versioned_plugin.sqlite.db"
s.files.delete "acts_as_versioned_plugin.sqlite3.db"
s.files.delete "test/debug.log"
s.require_path = 'lib'
s.autorequire = 'acts_as_versioned'
s.has_rdoc = true
s.test_files = Dir['test/**/*_test.rb']
s.add_dependency 'activerecord', '>= 1.10.1'
s.add_dependency 'activesupport', '>= 1.1.1'
s.author = "Rick Olson"
s.email = "technoweenie@gmail.com"
s.homepage = "http://techno-weenie.net"
end
Rake::GemPackageTask.new(spec) do |pkg|
pkg.need_tar = true
end
desc "Publish the API documentation"
task :pdoc => [:rdoc] do
Rake::RubyForgePublisher.new(RUBY_FORGE_PROJECT, RUBY_FORGE_USER).upload
end
desc 'Publish the gem and API docs'
task :publish => [:pdoc, :rubyforge_upload]
desc "Publish the release files to RubyForge."
task :rubyforge_upload => :package do
files = %w(gem tgz).map { |ext| "pkg/#{PKG_FILE_NAME}.#{ext}" }
if RUBY_FORGE_PROJECT then
require 'net/http'
require 'open-uri'
project_uri = "http://rubyforge.org/projects/#{RUBY_FORGE_PROJECT}/"
project_data = open(project_uri) { |data| data.read }
group_id = project_data[/[?&]group_id=(\d+)/, 1]
raise "Couldn't get group id" unless group_id
# This echos password to shell which is a bit sucky
if ENV["RUBY_FORGE_PASSWORD"]
password = ENV["RUBY_FORGE_PASSWORD"]
else
print "#{RUBY_FORGE_USER}@rubyforge.org's password: "
password = STDIN.gets.chomp
end
login_response = Net::HTTP.start("rubyforge.org", 80) do |http|
data = [
"login=1",
"form_loginname=#{RUBY_FORGE_USER}",
"form_pw=#{password}"
].join("&")
http.post("/account/login.php", data)
end
cookie = login_response["set-cookie"]
raise "Login failed" unless cookie
headers = { "Cookie" => cookie }
release_uri = "http://rubyforge.org/frs/admin/?group_id=#{group_id}"
release_data = open(release_uri, headers) { |data| data.read }
package_id = release_data[/[?&]package_id=(\d+)/, 1]
raise "Couldn't get package id" unless package_id
first_file = true
release_id = ""
files.each do |filename|
basename = File.basename(filename)
file_ext = File.extname(filename)
file_data = File.open(filename, "rb") { |file| file.read }
puts "Releasing #{basename}..."
release_response = Net::HTTP.start("rubyforge.org", 80) do |http|
release_date = Time.now.strftime("%Y-%m-%d %H:%M")
type_map = {
".zip" => "3000",
".tgz" => "3110",
".gz" => "3110",
".gem" => "1400"
}; type_map.default = "9999"
type = type_map[file_ext]
boundary = "rubyqMY6QN9bp6e4kS21H4y0zxcvoor"
query_hash = if first_file then
{
"group_id" => group_id,
"package_id" => package_id,
"release_name" => PKG_FILE_NAME,
"release_date" => release_date,
"type_id" => type,
"processor_id" => "8000", # Any
"release_notes" => "",
"release_changes" => "",
"preformatted" => "1",
"submit" => "1"
}
else
{
"group_id" => group_id,
"release_id" => release_id,
"package_id" => package_id,
"step2" => "1",
"type_id" => type,
"processor_id" => "8000", # Any
"submit" => "Add This File"
}
end
query = "?" + query_hash.map do |(name, value)|
[name, URI.encode(value)].join("=")
end.join("&")
data = [
"--" + boundary,
"Content-Disposition: form-data; name=\"userfile\"; filename=\"#{basename}\"",
"Content-Type: application/octet-stream",
"Content-Transfer-Encoding: binary",
"", file_data, ""
].join("\x0D\x0A")
release_headers = headers.merge(
"Content-Type" => "multipart/form-data; boundary=#{boundary}"
)
target = first_file ? "/frs/admin/qrs.php" : "/frs/admin/editrelease.php"
http.post(target + query, data, release_headers)
end
if first_file then
release_id = release_response.body[/release_id=(\d+)/, 1]
raise("Couldn't get release id") unless release_id
end
first_file = false
end
end
end

View file

@ -126,7 +126,7 @@ Redmine::AccessControl.map do |map|
map.permission :log_time, {:timelog => [:new, :create]}, :require => :loggedin
map.permission :edit_time_entries, {:timelog => [:edit, :update, :destroy, :bulk_edit, :bulk_update]}, :require => :member
map.permission :edit_own_time_entries, {:timelog => [:edit, :update, :destroy,:bulk_edit, :bulk_update]}, :require => :loggedin
map.permission :manage_project_activities, {:project_enumerations => [:update, :destroy]}, :require => :member
map.permission :manage_project_activities, {:projects => :settings, :project_enumerations => [:update, :destroy]}, :require => :member
end
map.project_module :news do |map|
@ -164,7 +164,7 @@ Redmine::AccessControl.map do |map|
map.permission :browse_repository, {:repositories => [:show, :browse, :entry, :raw, :annotate, :changes, :diff, :stats, :graph]}, :read => true
map.permission :commit_access, {}
map.permission :manage_related_issues, {:repositories => [:add_related_issue, :remove_related_issue]}
map.permission :manage_repository, {:repositories => [:new, :create, :edit, :update, :committers, :destroy]}, :require => :member
map.permission :manage_repository, {:projects => :settings, :repositories => [:new, :create, :edit, :update, :committers, :destroy]}, :require => :member
end
map.project_module :boards do |map|
@ -174,7 +174,7 @@ Redmine::AccessControl.map do |map|
map.permission :edit_own_messages, {:messages => :edit, :attachments => :upload}, :require => :loggedin
map.permission :delete_messages, {:messages => :destroy}, :require => :member
map.permission :delete_own_messages, {:messages => :destroy}, :require => :loggedin
map.permission :manage_boards, {:boards => [:new, :create, :edit, :update, :destroy]}, :require => :member
map.permission :manage_boards, {:projects => :settings, :boards => [:new, :create, :edit, :update, :destroy]}, :require => :member
end
map.project_module :calendar do |map|

View file

@ -33,7 +33,7 @@ module Redmine
c.iv = iv
e = c.update(text.to_s)
e << c.final
"aes-256-cbc:" + [e, iv].map {|v| Base64.encode64(v).strip}.join('--')
"aes-256-cbc:" + [e, iv].map {|v| Base64.strict_encode64(v)}.join('--')
end
end

View file

@ -486,7 +486,7 @@ module Redmine
def validate_single_value(custom_field, value, customized=nil)
errs = super
errs << ::I18n.t('activerecord.errors.messages.not_a_number') unless value.to_s =~ /^[+-]?\d+$/
errs << ::I18n.t('activerecord.errors.messages.not_a_number') unless value.to_s.strip =~ /^[+-]?\d+$/
errs
end
@ -736,6 +736,16 @@ module Redmine
options
end
def validate_custom_value(custom_value)
values = Array.wrap(custom_value.value).reject {|value| value.to_s == ''}
invalid_values = values - possible_custom_value_options(custom_value).map(&:last)
if invalid_values.any?
[::I18n.t('activerecord.errors.messages.inclusion')]
else
[]
end
end
def order_statement(custom_field)
if target_class.respond_to?(:fields_for_order_statement)
target_class.fields_for_order_statement(value_join_alias(custom_field))

View file

@ -81,7 +81,7 @@ module Redmine
# below : list unreadable files, but dont link them.
:path => utf_8_path,
:kind => (File.directory?(t1) ? 'dir' : 'file'),
:size => (File.directory?(t1) ? nil : [File.size(t1)].pack('l').unpack('L').first),
:size => (File.directory?(t1) ? nil : File.size(t1)),
:lastrev =>
Revision.new({:time => (File.mtime(t1)) })
})

View file

@ -83,6 +83,7 @@ module Redmine
io.each_line do |line|
branch_rev = line.match('\s*(\*?)\s*(.*?)\s*([0-9a-f]{40}).*$')
bran = GitBranch.new(branch_rev[2])
next unless branch_rev
bran.revision = branch_rev[3]
bran.scmid = branch_rev[3]
bran.is_default = ( branch_rev[1] == '*' )

View file

@ -46,14 +46,22 @@ Output example of rhmanifest::
</rhmanifest>
"""
import re, time, cgi, urllib
from mercurial import cmdutil, commands, node, error, hg
from mercurial import cmdutil, commands, node, error, hg, registrar
cmdtable = {}
command = cmdutil.command(cmdtable)
command = registrar.command(cmdtable) if hasattr(registrar, 'command') else cmdutil.command(cmdtable)
_x = cgi.escape
_u = lambda s: cgi.escape(urllib.quote(s))
def _changectx(repo, rev):
if isinstance(rev, str):
rev = repo.lookup(rev)
if hasattr(repo, 'changectx'):
return repo.changectx(rev)
else:
return repo[rev]
def _tip(ui, repo):
# see mercurial/commands.py:tip
def tiprev():
@ -61,7 +69,7 @@ def _tip(ui, repo):
return len(repo) - 1
except TypeError: # Mercurial < 1.1
return repo.changelog.count() - 1
tipctx = repo.changectx(tiprev())
tipctx = _changectx(repo, tiprev())
ui.write('<tip revision="%d" node="%s"/>\n'
% (tipctx.rev(), _x(node.hex(tipctx.node()))))
@ -94,13 +102,18 @@ def _branches(ui, repo):
return repo.branchheads(branch, closed=False)
except TypeError: # Mercurial < 1.2
return repo.branchheads(branch)
def lookup(rev, n):
try:
return repo.lookup(rev)
except RuntimeError:
return n
for t, n, r in sorted(iterbranches(), key=lambda e: e[2], reverse=True):
if repo.lookup(r) in branchheads(t):
if lookup(r, n) in branchheads(t):
ui.write('<branch revision="%d" node="%s" name="%s"/>\n'
% (r, _x(node.hex(n)), _x(t)))
def _manifest(ui, repo, path, rev):
ctx = repo.changectx(rev)
ctx = _changectx(repo, rev)
ui.write('<manifest revision="%d" path="%s">\n'
% (ctx.rev(), _u(path)))
@ -155,7 +168,7 @@ def rhdiff(ui, repo, *pats, **opts):
"""diff repository (or selected files)"""
change = opts.pop('change', None)
if change: # add -c option for Mercurial<1.1
base = repo.changectx(change).parents()[0].rev()
base = _changectx(repo, change).parents()[0].rev()
opts['rev'] = [str(base), change]
opts['nodates'] = True
return commands.diff(ui, repo, *map(urllib.unquote_plus, pats), **opts)

View file

@ -87,6 +87,7 @@ module Redmine
private
def normalize!
self.reject! {|s| s.first.blank? }
self.collect! {|s| s = Array(s); [s.first, (s.last == false || s.last.to_s == 'desc') ? 'desc' : 'asc']}
self.slice!(3)
self

View file

@ -49,7 +49,12 @@ module Redmine
def self.convert_available?
return @convert_available if defined?(@convert_available)
@convert_available = system("#{shell_quote CONVERT_BIN} -version") rescue false
begin
`#{shell_quote CONVERT_BIN} -version`
@convert_available = $?.success?
rescue
@convert_available = false
end
logger.warn("Imagemagick's convert binary (#{CONVERT_BIN}) not available") unless @convert_available
@convert_available
end

View file

@ -4,7 +4,7 @@ module Redmine
module VERSION #:nodoc:
MAJOR = 3
MINOR = 4
TINY = 4
TINY = 13
# Branch values:
# * official release: nil

View file

@ -48,7 +48,7 @@ module Redmine
end
def method_missing(sym, *args, &block)
if args.any?
if args.count > 0
if args.first.is_a?(Hash)
if @struct.last.is_a?(Array)
@struct.last << args.first unless block

View file

@ -94,15 +94,13 @@ module Redmine
i = 0
l = 1
inside_pre = false
@text.split(/(^(?:.+\r?\n\r?(?:\=+|\-+)|#+.+|~~~.*)\s*$)/).each do |part|
@text.split(/(^(?:.+\r?\n\r?(?:\=+|\-+)|#+.+|(?:~~~|```).*)\s*$)/).each do |part|
level = nil
if part =~ /\A~{3,}(\S+)?\s*$/
if $1
if !inside_pre
inside_pre = true
end
else
inside_pre = !inside_pre
if part =~ /\A(~{3,}|`{3,})(\S+)?\s*$/
if !inside_pre
inside_pre = true
elsif !$2
inside_pre = false
end
elsif inside_pre
# nop
@ -142,7 +140,8 @@ module Redmine
:strikethrough => true,
:superscript => true,
:no_intra_emphasis => true,
:footnotes => true
:footnotes => true,
:lax_spacing => true
)
end
end

View file

@ -120,9 +120,10 @@ module Redmine
## replace <pre> content
text.gsub!(/<redpre#(\d+)>/) do
content = @pre_list[$1.to_i]
if content.match(/<code\s+class="(\w+)">\s?(.+)/m)
language = $1
text = $2
# This regex must match any data produced by RedCloth3#rip_offtags
if content.match(/<code\s+class=(?:"([^"]+)"|'([^']+)')>\s?(.*)/m)
language = $1 || $2
text = $3
if Redmine::SyntaxHighlighting.language_supported?(language)
content = "<code class=\"#{language} syntaxhl\">" +
Redmine::SyntaxHighlighting.highlight_by_language(text, language)

View file

@ -343,7 +343,7 @@ class RedCloth3 < String
A_VLGN = /[\-^~]/
C_CLAS = '(?:\([^")]+\))'
C_LNGE = '(?:\[[a-z\-_]+\])'
C_STYL = '(?:\{[^"}]+\})'
C_STYL = '(?:\{[^{][^"}]+\})'
S_CSPN = '(?:\\\\\d+)'
S_RSPN = '(?:/\d+)'
A = "(?:#{A_HLGN}?#{A_VLGN}?|#{A_VLGN}?#{A_HLGN}?)"
@ -1034,7 +1034,7 @@ class RedCloth3 < String
def flush_left( text )
indt = 0
if text =~ /^ /
while text !~ /^ {#{indt}}\S/
while text !~ /^ {#{indt}}[^ ]/
indt += 1
end unless text.empty?
if indt.nonzero?
@ -1049,7 +1049,7 @@ class RedCloth3 < String
end
OFFTAGS = /(code|pre|kbd|notextile)/
OFFTAG_MATCH = /(?:(<\/#{ OFFTAGS }>)|(<#{ OFFTAGS }[^>]*>))(.*?)(?=<\/?#{ OFFTAGS }\W|\Z)/mi
OFFTAG_MATCH = /(?:(<\/#{ OFFTAGS }\b>)|(<#{ OFFTAGS }\b[^>]*>))(.*?)(?=<\/?#{ OFFTAGS }\b\W|\Z)/mi
OFFTAG_OPEN = /<#{ OFFTAGS }/
OFFTAG_CLOSE = /<\/?#{ OFFTAGS }/
HASTAG_MATCH = /(<\/?\w[^\n]*?>)/m
@ -1213,7 +1213,13 @@ class RedCloth3 < String
ALLOWED_TAGS = %w(redpre pre code kbd notextile)
def escape_html_tags(text)
text.gsub!(%r{<(\/?([!\w]+)[^<>\n]*)(>?)}) {|m| ALLOWED_TAGS.include?($2) ? "<#{$1}#{$3}" : "&lt;#{$1}#{'&gt;' unless $3.blank?}" }
text.gsub!(%r{<(\/?([!\w]+)[^<>\n]*)(>?)}) do |m|
if ALLOWED_TAGS.include?($2) && $3.present?
"<#{$1}#{$3}"
else
"&lt;#{$1}#{'&gt;' unless $3.blank?}"
end
end
end
end