annotate lib/redmine/scm/adapters/bazaar_adapter.rb @ 8:0c83d98252d9 yuya

* Add custom repo prefix and proper auth realm, remove auth cache (seems like an unwise feature), pass DB handle around, various other bits of tidying
author Chris Cannam
date Thu, 12 Aug 2010 15:31:37 +0100
parents 513646585e45
children af80e5618e9b
rev   line source
Chris@0 1 # redMine - project management software
Chris@0 2 # Copyright (C) 2006-2007 Jean-Philippe Lang
Chris@0 3 #
Chris@0 4 # This program is free software; you can redistribute it and/or
Chris@0 5 # modify it under the terms of the GNU General Public License
Chris@0 6 # as published by the Free Software Foundation; either version 2
Chris@0 7 # of the License, or (at your option) any later version.
Chris@0 8 #
Chris@0 9 # This program is distributed in the hope that it will be useful,
Chris@0 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
Chris@0 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
Chris@0 12 # GNU General Public License for more details.
Chris@0 13 #
Chris@0 14 # You should have received a copy of the GNU General Public License
Chris@0 15 # along with this program; if not, write to the Free Software
Chris@0 16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
Chris@0 17
Chris@0 18 require 'redmine/scm/adapters/abstract_adapter'
Chris@0 19
Chris@0 20 module Redmine
Chris@0 21 module Scm
Chris@0 22 module Adapters
Chris@0 23 class BazaarAdapter < AbstractAdapter
Chris@0 24
Chris@0 25 # Bazaar executable name
Chris@0 26 BZR_BIN = "bzr"
Chris@0 27
Chris@0 28 # Get info about the repository
Chris@0 29 def info
Chris@0 30 cmd = "#{BZR_BIN} revno #{target('')}"
Chris@0 31 info = nil
Chris@0 32 shellout(cmd) do |io|
Chris@0 33 if io.read =~ %r{^(\d+)\r?$}
Chris@0 34 info = Info.new({:root_url => url,
Chris@0 35 :lastrev => Revision.new({
Chris@0 36 :identifier => $1
Chris@0 37 })
Chris@0 38 })
Chris@0 39 end
Chris@0 40 end
Chris@0 41 return nil if $? && $?.exitstatus != 0
Chris@0 42 info
Chris@0 43 rescue CommandFailed
Chris@0 44 return nil
Chris@0 45 end
Chris@0 46
Chris@0 47 # Returns an Entries collection
Chris@0 48 # or nil if the given path doesn't exist in the repository
Chris@0 49 def entries(path=nil, identifier=nil)
Chris@0 50 path ||= ''
Chris@0 51 entries = Entries.new
Chris@0 52 cmd = "#{BZR_BIN} ls -v --show-ids"
Chris@0 53 identifier = -1 unless identifier && identifier.to_i > 0
Chris@0 54 cmd << " -r#{identifier.to_i}"
Chris@0 55 cmd << " #{target(path)}"
Chris@0 56 shellout(cmd) do |io|
Chris@0 57 prefix = "#{url}/#{path}".gsub('\\', '/')
Chris@0 58 logger.debug "PREFIX: #{prefix}"
Chris@0 59 re = %r{^V\s+(#{Regexp.escape(prefix)})?(\/?)([^\/]+)(\/?)\s+(\S+)\r?$}
Chris@0 60 io.each_line do |line|
Chris@0 61 next unless line =~ re
Chris@0 62 entries << Entry.new({:name => $3.strip,
Chris@0 63 :path => ((path.empty? ? "" : "#{path}/") + $3.strip),
Chris@0 64 :kind => ($4.blank? ? 'file' : 'dir'),
Chris@0 65 :size => nil,
Chris@0 66 :lastrev => Revision.new(:revision => $5.strip)
Chris@0 67 })
Chris@0 68 end
Chris@0 69 end
Chris@0 70 return nil if $? && $?.exitstatus != 0
Chris@0 71 logger.debug("Found #{entries.size} entries in the repository for #{target(path)}") if logger && logger.debug?
Chris@0 72 entries.sort_by_name
Chris@0 73 end
Chris@0 74
Chris@0 75 def revisions(path=nil, identifier_from=nil, identifier_to=nil, options={})
Chris@0 76 path ||= ''
Chris@0 77 identifier_from = 'last:1' unless identifier_from and identifier_from.to_i > 0
Chris@0 78 identifier_to = 1 unless identifier_to and identifier_to.to_i > 0
Chris@0 79 revisions = Revisions.new
Chris@0 80 cmd = "#{BZR_BIN} log -v --show-ids -r#{identifier_to.to_i}..#{identifier_from} #{target(path)}"
Chris@0 81 shellout(cmd) do |io|
Chris@0 82 revision = nil
Chris@0 83 parsing = nil
Chris@0 84 io.each_line do |line|
Chris@0 85 if line =~ /^----/
Chris@0 86 revisions << revision if revision
Chris@0 87 revision = Revision.new(:paths => [], :message => '')
Chris@0 88 parsing = nil
Chris@0 89 else
Chris@0 90 next unless revision
Chris@0 91
Chris@0 92 if line =~ /^revno: (\d+)($|\s\[merge\]$)/
Chris@0 93 revision.identifier = $1.to_i
Chris@0 94 elsif line =~ /^committer: (.+)$/
Chris@0 95 revision.author = $1.strip
Chris@0 96 elsif line =~ /^revision-id:(.+)$/
Chris@0 97 revision.scmid = $1.strip
Chris@0 98 elsif line =~ /^timestamp: (.+)$/
Chris@0 99 revision.time = Time.parse($1).localtime
Chris@0 100 elsif line =~ /^ -----/
Chris@0 101 # partial revisions
Chris@0 102 parsing = nil unless parsing == 'message'
Chris@0 103 elsif line =~ /^(message|added|modified|removed|renamed):/
Chris@0 104 parsing = $1
Chris@0 105 elsif line =~ /^ (.*)$/
Chris@0 106 if parsing == 'message'
Chris@0 107 revision.message << "#{$1}\n"
Chris@0 108 else
Chris@0 109 if $1 =~ /^(.*)\s+(\S+)$/
Chris@0 110 path = $1.strip
Chris@0 111 revid = $2
Chris@0 112 case parsing
Chris@0 113 when 'added'
Chris@0 114 revision.paths << {:action => 'A', :path => "/#{path}", :revision => revid}
Chris@0 115 when 'modified'
Chris@0 116 revision.paths << {:action => 'M', :path => "/#{path}", :revision => revid}
Chris@0 117 when 'removed'
Chris@0 118 revision.paths << {:action => 'D', :path => "/#{path}", :revision => revid}
Chris@0 119 when 'renamed'
Chris@0 120 new_path = path.split('=>').last
Chris@0 121 revision.paths << {:action => 'M', :path => "/#{new_path.strip}", :revision => revid} if new_path
Chris@0 122 end
Chris@0 123 end
Chris@0 124 end
Chris@0 125 else
Chris@0 126 parsing = nil
Chris@0 127 end
Chris@0 128 end
Chris@0 129 end
Chris@0 130 revisions << revision if revision
Chris@0 131 end
Chris@0 132 return nil if $? && $?.exitstatus != 0
Chris@0 133 revisions
Chris@0 134 end
Chris@0 135
Chris@0 136 def diff(path, identifier_from, identifier_to=nil)
Chris@0 137 path ||= ''
Chris@0 138 if identifier_to
Chris@0 139 identifier_to = identifier_to.to_i
Chris@0 140 else
Chris@0 141 identifier_to = identifier_from.to_i - 1
Chris@0 142 end
Chris@0 143 cmd = "#{BZR_BIN} diff -r#{identifier_to}..#{identifier_from} #{target(path)}"
Chris@0 144 diff = []
Chris@0 145 shellout(cmd) do |io|
Chris@0 146 io.each_line do |line|
Chris@0 147 diff << line
Chris@0 148 end
Chris@0 149 end
Chris@0 150 #return nil if $? && $?.exitstatus != 0
Chris@0 151 diff
Chris@0 152 end
Chris@0 153
Chris@0 154 def cat(path, identifier=nil)
Chris@0 155 cmd = "#{BZR_BIN} cat"
Chris@0 156 cmd << " -r#{identifier.to_i}" if identifier && identifier.to_i > 0
Chris@0 157 cmd << " #{target(path)}"
Chris@0 158 cat = nil
Chris@0 159 shellout(cmd) do |io|
Chris@0 160 io.binmode
Chris@0 161 cat = io.read
Chris@0 162 end
Chris@0 163 return nil if $? && $?.exitstatus != 0
Chris@0 164 cat
Chris@0 165 end
Chris@0 166
Chris@0 167 def annotate(path, identifier=nil)
Chris@0 168 cmd = "#{BZR_BIN} annotate --all"
Chris@0 169 cmd << " -r#{identifier.to_i}" if identifier && identifier.to_i > 0
Chris@0 170 cmd << " #{target(path)}"
Chris@0 171 blame = Annotate.new
Chris@0 172 shellout(cmd) do |io|
Chris@0 173 author = nil
Chris@0 174 identifier = nil
Chris@0 175 io.each_line do |line|
Chris@0 176 next unless line =~ %r{^(\d+) ([^|]+)\| (.*)$}
Chris@0 177 blame.add_line($3.rstrip, Revision.new(:identifier => $1.to_i, :author => $2.strip))
Chris@0 178 end
Chris@0 179 end
Chris@0 180 return nil if $? && $?.exitstatus != 0
Chris@0 181 blame
Chris@0 182 end
Chris@0 183 end
Chris@0 184 end
Chris@0 185 end
Chris@0 186 end