-# redMine - project management software
-# Copyright (C) 2006-2007 Jean-Philippe Lang
+# Redmine - project management software
+# Copyright (C) 2006-2011 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
-#
+#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
-#
+#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
module Adapters
class GitAdapter < AbstractAdapter
- SCM_GIT_REPORT_LAST_COMMIT = true
-
# Git executable name
GIT_BIN = Redmine::Configuration['scm_git_command'] || "git"
def initialize(url, root_url=nil, login=nil, password=nil, path_encoding=nil)
super
- @path_encoding = path_encoding || 'UTF-8'
- @flag_report_last_commit = SCM_GIT_REPORT_LAST_COMMIT
+ @path_encoding = path_encoding.blank? ? 'UTF-8' : path_encoding
+ end
+
+ def path_encoding
+ @path_encoding
end
def info
def branches
return @branches if @branches
@branches = []
- cmd = "#{self.class.sq_bin} --git-dir #{target('')} branch --no-color"
- shellout(cmd) do |io|
+ cmd_args = %w|branch --no-color|
+ scm_cmd(*cmd_args) do |io|
io.each_line do |line|
@branches << line.match('\s*\*?\s*(.*)$')[1]
end
end
@branches.sort!
+ rescue ScmCommandAborted
+ nil
end
def tags
return @tags if @tags
- cmd = "#{self.class.sq_bin} --git-dir #{target('')} tag"
- shellout(cmd) do |io|
+ cmd_args = %w|tag|
+ scm_cmd(*cmd_args) do |io|
@tags = io.readlines.sort!.map{|t| t.strip}
end
+ rescue ScmCommandAborted
+ nil
end
def default_branch
- branches.include?('master') ? 'master' : branches.first
+ bras = self.branches
+ return nil if bras.nil?
+ bras.include?('master') ? 'master' : bras.first
+ end
+
+ def entry(path=nil, identifier=nil)
+ parts = path.to_s.split(%r{[\/\\]}).select {|n| !n.blank?}
+ search_path = parts[0..-2].join('/')
+ search_name = parts[-1]
+ if search_path.blank? && search_name.blank?
+ # Root entry
+ Entry.new(:path => '', :kind => 'dir')
+ else
+ # Search for the entry in the parent directory
+ es = entries(search_path, identifier,
+ options = {:report_last_commit => false})
+ es ? es.detect {|e| e.name == search_name} : nil
+ end
end
- def entries(path=nil, identifier=nil)
+ def entries(path=nil, identifier=nil, options={})
path ||= ''
p = scm_iconv(@path_encoding, 'UTF-8', path)
entries = Entries.new
sha = $2
size = $3
name = $4
- full_path = path.empty? ? name : "#{path}/#{name}"
+ if name.respond_to?(:force_encoding)
+ name.force_encoding(@path_encoding)
+ end
+ full_path = p.empty? ? name : "#{p}/#{name}"
n = scm_iconv('UTF-8', @path_encoding, name)
full_p = scm_iconv('UTF-8', @path_encoding, full_path)
entries << Entry.new({:name => n,
:path => full_p,
:kind => (type == "tree") ? 'dir' : 'file',
:size => (type == "tree") ? nil : size,
- :lastrev => @flag_report_last_commit ? lastrev(full_path, identifier) : Revision.new
+ :lastrev => options[:report_last_commit] ?
+ lastrev(full_path, identifier) : Revision.new
}) unless entries.detect{|entry| entry.name == name}
end
end
def lastrev(path, rev)
return nil if path.nil?
cmd_args = %w|log --no-color --encoding=UTF-8 --date=iso --pretty=fuller --no-merges -n 1|
- cmd_args << rev if rev
+ cmd_args << rev if rev
cmd_args << "--" << path unless path.empty?
lines = []
scm_cmd(*cmd_args) { |io| lines = io.readlines }
Revision.new({
:identifier => id,
- :scmid => id,
- :author => author,
- :time => time,
- :message => nil,
- :paths => nil
+ :scmid => id,
+ :author => author,
+ :time => time,
+ :message => nil,
+ :paths => nil
})
rescue NoMethodError => e
logger.error("The revision '#{path}' has a wrong format")
end
def revisions(path, identifier_from, identifier_to, options={})
- revisions = Revisions.new
+ revs = Revisions.new
cmd_args = %w|log --no-color --encoding=UTF-8 --raw --date=iso --pretty=fuller|
cmd_args << "--reverse" if options[:reverse]
cmd_args << "--all" if options[:all]
parsing_descr = 0
revision = Revision.new({
:identifier => changeset[:commit],
- :scmid => changeset[:commit],
- :author => changeset[:author],
- :time => Time.parse(changeset[:date]),
- :message => changeset[:description],
- :paths => files
+ :scmid => changeset[:commit],
+ :author => changeset[:author],
+ :time => Time.parse(changeset[:date]),
+ :message => changeset[:description],
+ :paths => files
})
if block_given?
yield revision
else
- revisions << revision
+ revs << revision
end
changeset = {}
files = []
if changeset[:commit]
revision = Revision.new({
:identifier => changeset[:commit],
- :scmid => changeset[:commit],
- :author => changeset[:author],
- :time => Time.parse(changeset[:date]),
- :message => changeset[:description],
- :paths => files
- })
-
+ :scmid => changeset[:commit],
+ :author => changeset[:author],
+ :time => Time.parse(changeset[:date]),
+ :message => changeset[:description],
+ :paths => files
+ })
if block_given?
yield revision
else
- revisions << revision
+ revs << revision
end
end
end
- revisions
- rescue ScmCommandAborted
- revisions
+ revs
+ rescue ScmCommandAborted => e
+ logger.error("git log #{from_to.to_s} error: #{e.message}")
+ revs
end
def diff(path, identifier_from, identifier_to=nil)
elsif line =~ /^\t(.*)/
blame.add_line($1, Revision.new(
:identifier => identifier,
- :author => authors_by_commit[identifier]))
+ :revision => identifier,
+ :scmid => identifier,
+ :author => authors_by_commit[identifier]
+ ))
identifier = ''
author = ''
end
def scm_cmd(*args, &block)
repo_path = root_url || url
full_args = [GIT_BIN, '--git-dir', repo_path]
+ if self.class.client_version_above?([1, 7, 2])
+ full_args << '-c' << 'core.quotepath=false'
+ full_args << '-c' << 'log.decorate=no'
+ end
full_args += args
ret = shellout(full_args.map { |e| shell_quote e.to_s }.join(' '), &block)
if $? && $?.exitstatus != 0