diff -uNr redmine/lib/redmine/scm/adapters/git_adapter.rb redmine_argos_gitbranches/lib/redmine/scm/adapters/git_adapter.rb --- redmine/lib/redmine/scm/adapters/git_adapter.rb 2009-01-28 23:30:02.000000000 +0100 +++ redmine_argos_gitbranches/lib/redmine/scm/adapters/git_adapter.rb 2009-02-23 07:13:11.000000000 +0100 @@ -26,74 +26,84 @@ GIT_BIN = "git" # Get the revision of a particuliar file - def get_rev (rev,path) - - if rev != 'latest' && !rev.nil? - cmd="#{GIT_BIN} --git-dir #{target('')} show --date=iso --pretty=fuller #{shell_quote rev} -- #{shell_quote path}" - else - @branch ||= shellout("#{GIT_BIN} --git-dir #{target('')} branch") { |io| io.grep(/\*/)[0].strip.match(/\* (.*)/)[1] } - cmd="#{GIT_BIN} --git-dir #{target('')} log --date=iso --pretty=fuller -1 #{@branch} -- #{shell_quote path}" - end - rev=[] - i=0 - shellout(cmd) do |io| - files=[] - changeset = {} - parsing_descr = 0 #0: not parsing desc or files, 1: parsing desc, 2: parsing files + def get_rev (rev,treepath) + if treepath =~ /^refs\/([^\/]+)\/([^\/]+)\/(.*)$/ + type = $1 + tree = $2 + path = $3 + type_tree = "#{type}/#{tree}" + else + path ||= '' + type_tree ||= '' + #return nil + end + if rev != 'latest' && !rev.nil? + #cmd="#{GIT_BIN} --git-dir #{target('')} show --raw --date=iso --pretty=fuller #{shell_quote rev} #{shell_quote type_tree} -- #{shell_quote path}" + cmd="#{GIT_BIN} --git-dir #{target('')} show --raw --date=iso --pretty=fuller -1 #{shell_quote rev} -- #{shell_quote path}" + else + #@branch ||= shellout("#{GIT_BIN} --git-dir #{target('')} branch") { |io| io.grep(/\*/)[0].strip.match(/\* (.*)/)[1] } + cmd="#{GIT_BIN} --git-dir #{target('')} log --raw --date=iso --pretty=fuller -1 #{type_tree} -- #{shell_quote path}" + end + rev=[] + i=0 + shellout(cmd) do |io| + files=[] + changeset = {} + parsing_descr = 0 #0: not parsing desc or files, 1: parsing desc, 2: parsing files + + io.each_line do |line| + if line =~ /^commit ([0-9a-f]{40})$/ + key = "commit" + value = $1 + if (parsing_descr == 1 || parsing_descr == 2) + parsing_descr = 0 + rev = Revision.new({:identifier => changeset[:commit], + :scmid => changeset[:commit], + :author => changeset[:author], + :time => Time.parse(changeset[:date]), + :message => changeset[:description], + :paths => files + }) + changeset = {} + files = [] + end + changeset[:commit] = $1 + elsif (parsing_descr == 0) && line =~ /^(\w+):\s*(.*)$/ + key = $1 + value = $2 + if key == "Author" + changeset[:author] = value + elsif key == "CommitDate" + changeset[:date] = value + end + elsif (parsing_descr == 0) && line.chomp.to_s == "" + parsing_descr = 1 + changeset[:description] = "" + elsif (parsing_descr == 1 || parsing_descr == 2) && line =~ /^:\d+\s+\d+\s+[0-9a-f.]+\s+[0-9a-f.]+\s+(\w)\s+(.+)$/ + parsing_descr = 2 + fileaction = $1 + filepath = $2 + files << {:action => fileaction, :path => "refs/#{type_tree}/#{filepath}"} + elsif (parsing_descr == 1) && line.chomp.to_s == "" + parsing_descr = 2 + elsif (parsing_descr == 1) + changeset[:description] << line + end + end + rev = Revision.new({:identifier => changeset[:commit], + :scmid => changeset[:commit], + :author => changeset[:author], + :time => (changeset[:date] ? Time.parse(changeset[:date]) : nil), + :message => changeset[:description], + :paths => files + }) - io.each_line do |line| - if line =~ /^commit ([0-9a-f]{40})$/ - key = "commit" - value = $1 - if (parsing_descr == 1 || parsing_descr == 2) - parsing_descr = 0 - rev = Revision.new({:identifier => changeset[:commit], - :scmid => changeset[:commit], - :author => changeset[:author], - :time => Time.parse(changeset[:date]), - :message => changeset[:description], - :paths => files - }) - changeset = {} - files = [] - end - changeset[:commit] = $1 - elsif (parsing_descr == 0) && line =~ /^(\w+):\s*(.*)$/ - key = $1 - value = $2 - if key == "Author" - changeset[:author] = value - elsif key == "CommitDate" - changeset[:date] = value - end - elsif (parsing_descr == 0) && line.chomp.to_s == "" - parsing_descr = 1 - changeset[:description] = "" - elsif (parsing_descr == 1 || parsing_descr == 2) && line =~ /^:\d+\s+\d+\s+[0-9a-f.]+\s+[0-9a-f.]+\s+(\w)\s+(.+)$/ - parsing_descr = 2 - fileaction = $1 - filepath = $2 - files << {:action => fileaction, :path => filepath} - elsif (parsing_descr == 1) && line.chomp.to_s == "" - parsing_descr = 2 - elsif (parsing_descr == 1) - changeset[:description] << line - end - end - rev = Revision.new({:identifier => changeset[:commit], - :scmid => changeset[:commit], - :author => changeset[:author], - :time => (changeset[:date] ? Time.parse(changeset[:date]) : nil), - :message => changeset[:description], - :paths => files - }) + end - end - - get_rev('latest',path) if rev == [] + get_rev('latest',treepath) if rev == [] - return nil if $? && $?.exitstatus != 0 - return rev + return nil if $? && $?.exitstatus != 0 + return rev end def info @@ -107,115 +117,181 @@ return nil end - def entries(path=nil, identifier=nil) - path ||= '' - entries = Entries.new - cmd = "#{GIT_BIN} --git-dir #{target('')} ls-tree -l " - cmd << shell_quote("HEAD:" + path) if identifier.nil? - cmd << shell_quote(identifier + ":" + path) if identifier - shellout(cmd) do |io| - io.each_line do |line| - e = line.chomp.to_s - if e =~ /^\d+\s+(\w+)\s+([0-9a-f]{40})\s+([0-9-]+)\s+(.+)$/ - type = $1 - sha = $2 - size = $3 - name = $4 - entries << Entry.new({:name => name, - :path => (path.empty? ? name : "#{path}/#{name}"), - :kind => ((type == "tree") ? 'dir' : 'file'), - :size => ((type == "tree") ? nil : size), - :lastrev => get_rev(identifier,(path.empty? ? name : "#{path}/#{name}")) - - }) unless entries.detect{|entry| entry.name == name} - end - end - end - return nil if $? && $?.exitstatus != 0 - entries.sort_by_name + def entries(treepath=nil, identifier=nil) + treepath ||= '' + if treepath =~ /^refs\/([^\/]+)\/([^\/]+)\/(.*)$/ + type = $1 + tree = $2 + path = $3 + else + type = "heads" + tree = "master" + path = '' + end + path ||= '' + entries = Entries.new + if !treepath.empty? + type_tree = "#{type}/#{tree}" + cmd = "#{GIT_BIN} --git-dir #{target('')} ls-tree -l " + cmd << shell_quote(type_tree + ":" + path + (path.empty? ? "" : "/")) if identifier.nil? + cmd << shell_quote(identifier + ":" + path + (path.empty? ? "" : "/")) if identifier + shellout(cmd) do |io| + io.each_line do |line| + e = line.chomp.to_s + if e =~ /^\d+\s+(\w+)\s+([0-9a-f]{40})\s+([0-9-]+)\s+(.+)$/ + type = $1 + sha = $2 + size = $3 + name = $4 + entries << Entry.new({:name => name, + :path => (treepath.empty? ? name : "#{treepath}/#{name}"), + :kind => ((type == "tree") ? 'dir' : 'file'), + :size => ((type == "tree") ? nil : size), + #:lastrev => get_rev(identifier,(path.empty? ? name : "#{path}/#{name}")) + :lastrev => get_rev(identifier,(treepath.empty? ? name : "#{treepath}/#{name}")) + + }) unless entries.detect{|entry| entry.name == name} + end + end + end + else + cmd = "#{GIT_BIN} --git-dir #{target('')} for-each-ref --format=#{shell_quote('%(objectname) %(objecttype) %(refname)')} refs" + shellout(cmd) do |io| + io.each_line do |line| + e = line.chomp.to_s + if e =~ /^([0-9a-f]{40})\s+\w+\s+(.+)$/ + sha = $1 + refname = $2 + entries << Entry.new({:name => refname, + :path => refname, + #:path => (path.empty? ? refname : "#{path}/#{refname}"), + :kind => 'dir', + :size => nil, + :lastrev => get_rev(sha,(path.empty? ? refname : "#{path}/#{refname}")) + + }) unless entries.detect{|entry| entry.name == refname} + end + end + end + end + return nil if $? && $?.exitstatus != 0 + entries.sort_by_name end - def revisions(path, identifier_from, identifier_to, options={}) + def revisions(treepath, identifier_from, identifier_to, options={}) revisions = Revisions.new - cmd = "#{GIT_BIN} --git-dir #{target('')} log --raw --date=iso --pretty=fuller" - cmd << " --reverse" if options[:reverse] - cmd << " -n #{options[:limit].to_i} " if (!options.nil?) && options[:limit] - cmd << " #{shell_quote(identifier_from + '..')} " if identifier_from - cmd << " #{shell_quote identifier_to} " if identifier_to - shellout(cmd) do |io| - files=[] - changeset = {} - parsing_descr = 0 #0: not parsing desc or files, 1: parsing desc, 2: parsing files - revno = 1 - - io.each_line do |line| - if line =~ /^commit ([0-9a-f]{40})$/ - key = "commit" - value = $1 - if (parsing_descr == 1 || parsing_descr == 2) - 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 - }) - if block_given? - yield revision - else - revisions << revision - end - changeset = {} - files = [] - revno = revno + 1 - end - changeset[:commit] = $1 - elsif (parsing_descr == 0) && line =~ /^(\w+):\s*(.*)$/ - key = $1 - value = $2 - if key == "Author" - changeset[:author] = value - elsif key == "CommitDate" - changeset[:date] = value - end - elsif (parsing_descr == 0) && line.chomp.to_s == "" - parsing_descr = 1 - changeset[:description] = "" - elsif (parsing_descr == 1 || parsing_descr == 2) && line =~ /^:\d+\s+\d+\s+[0-9a-f.]+\s+[0-9a-f.]+\s+(\w)\s+(.+)$/ - parsing_descr = 2 - fileaction = $1 - filepath = $2 - files << {:action => fileaction, :path => filepath} - elsif (parsing_descr == 1) && line.chomp.to_s == "" - parsing_descr = 2 - elsif (parsing_descr == 1) - changeset[:description] << line[4..-1] - end - end - - 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 - }) - if block_given? - yield revision - else - revisions << revision - end - end - end + treepath ||= '' + if treepath =~ /^refs\/([^\/]+)\/([^\/]+)\/(.*)$/ + type = $1 + tree = $2 + path = $3 + type_tree = "#{type}/#{tree}" + else + path ||= '' + type_tree ||= '' + end + cmd = "#{GIT_BIN} --git-dir #{target('')} for-each-ref --format=#{shell_quote('%(objectname) %(objecttype) %(refname)')} refs" + shellout(cmd) do |io| + io.each_line do |line| + e = line.chomp.to_s + if e =~ /^([0-9a-f]{40})\s+\w+\s+(.+)$/ + sha = $1 + refname = $2 + + cmd = "#{GIT_BIN} --git-dir #{target('')} log --raw --date=iso --pretty=fuller" + cmd << " --reverse" if options[:reverse] + cmd << " -n #{options[:limit].to_i} " if (!options.nil?) && options[:limit] + cmd << " #{shell_quote(identifier_from + '..')} " if identifier_from + cmd << " #{shell_quote identifier_to} " if identifier_to + cmd << " #{shell_quote refname} " if identifier_from.nil? && identifier_to.nil? + shellout(cmd) do |io| + files=[] + changeset = {} + parsing_descr = 0 #0: not parsing desc or files, 1: parsing desc, 2: parsing files + revno = 1 + + io.each_line do |line| + if line =~ /^commit ([0-9a-f]{40})$/ + key = "commit" + value = $1 + if (parsing_descr == 1 || parsing_descr == 2) + 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 + }) + if block_given? + yield revision + else + revisions << revision + end + changeset = {} + files = [] + revno = revno + 1 + end + changeset[:commit] = $1 + elsif (parsing_descr == 0) && line =~ /^(\w+):\s*(.*)$/ + key = $1 + value = $2 + if key == "Author" + changeset[:author] = value + elsif key == "CommitDate" + changeset[:date] = value + end + elsif (parsing_descr == 0) && line.chomp.to_s == "" + parsing_descr = 1 + changeset[:description] = "" + elsif (parsing_descr == 1 || parsing_descr == 2) && line =~ /^:\d+\s+\d+\s+[0-9a-f.]+\s+[0-9a-f.]+\s+(\w)\s+(.+)$/ + parsing_descr = 2 + fileaction = $1 + filepath = $2 + files << {:action => fileaction, :path => "#{refname}/#{filepath}"} + elsif (parsing_descr == 1) && line.chomp.to_s == "" + parsing_descr = 2 + elsif (parsing_descr == 1) + changeset[:description] << line[4..-1] + end + end + + 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 + }) + if block_given? + yield revision + else + revisions << revision + end + end + end + end + end + end return nil if $? && $?.exitstatus != 0 revisions end - def diff(path, identifier_from, identifier_to=nil) - path ||= '' + def diff(treepath, identifier_from, identifier_to=nil) + treepath ||= '' + if treepath =~ /^refs\/([^\/]+)\/([^\/]+)\/(.*)$/ + type = $1 + tree = $2 + path = $3 + type_tree = "#{type}/#{tree}" + else + type = "heads" + tree = "master" + path ||= '' + type_tree = 'heads/master' + end if !identifier_to identifier_to = nil end @@ -233,7 +309,19 @@ diff end - def annotate(path, identifier=nil) + def annotate(treepath, identifier=nil) + treepath ||= '' + if treepath =~ /^refs\/([^\/]+)\/([^\/]+)\/(.*)$/ + type = $1 + tree = $2 + path = $3 + type_tree = "#{type}/#{tree}" + else + type = "heads" + tree = "master" + path = '' + type_tree = 'heads/master' + end identifier = 'HEAD' if identifier.blank? cmd = "#{GIT_BIN} --git-dir #{target('')} blame -l #{shell_quote identifier} -- #{shell_quote path}" blame = Annotate.new @@ -249,7 +337,19 @@ blame end - def cat(path, identifier=nil) + def cat(treepath, identifier=nil) + treepath ||= '' + if treepath =~ /^refs\/([^\/]+)\/([^\/]+)\/(.*)$/ + type = $1 + tree = $2 + path = $3 + type_tree = "#{type}/#{tree}" + else + type = "heads" + tree = "master" + path = '' + type_tree = 'heads/master' + end if identifier.nil? identifier = 'HEAD' end