Class: Git::Trac::Repository
- Inherits:
-
Object
- Object
- Git::Trac::Repository
- Defined in:
- lib/git/trac/pager.rb,
lib/git/trac/repository.rb
Instance Attribute Summary collapse
-
#git_dir ⇒ Object
readonly
Returns the value of attribute git_dir.
-
#options ⇒ Object
readonly
Returns the value of attribute options.
Instance Method Summary collapse
- #agent ⇒ Object
- #cleanup_branches(options, *revs) ⇒ Object
-
#config(arg1 = nil, arg2 = nil) ⇒ Object
Parse the output of git-config and return it as a hash.
- #current_checkout ⇒ Object
- #diff_hash(head) ⇒ Object
- #each_ref(*args) ⇒ Object
-
#exec(*args, &block) ⇒ Object
Invokes a command.
-
#generated_commits ⇒ Object
A hash of the form => ticket_number.
- #get_response(uri) ⇒ Object
-
#guess_current_ticket_number ⇒ Object
See if the current commit or an ancestor was previously tagged as a trac ticket.
- #guess_upstream(head = "HEAD") ⇒ Object
-
#in_work_tree(&block) ⇒ Object
Call the block while chdired to the working tree.
-
#initialize(dir = nil, options = {}) ⇒ Repository
constructor
A new instance of Repository.
- #inspect ⇒ Object
- #method_missing(method, *args, &block) ⇒ Object
- #pager(body, diff = false) ⇒ Object
-
#popen3(*args, &block) ⇒ Object
Open3.popen3 in the current working tree.
-
#reload ⇒ Object
:nodoc:.
-
#rev_parse(rev) ⇒ Object
Call git-rev-parse on a revision, returning nil if nothing is found.
-
#ticket(number) ⇒ Object
Fetch a ticket object by number.
-
#url ⇒ Object
The trac url associated with the repository.
- #with_index(file) ⇒ Object
-
#working_tickets ⇒ Object
Return ticket objects for each ticket referenced in the repository.
Constructor Details
#initialize(dir = nil, options = {}) ⇒ Repository
Returns a new instance of Repository.
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
# File 'lib/git/trac/repository.rb', line 10 def initialize(dir = nil, = {}) , dir = dir, nil if dir.kind_of?(Hash) dir ||= ENV["GIT_DIR"] dir ||= Dir.getwd Dir.chdir(dir) do @git_dir = Open3.popen3("git","rev-parse","--git-dir") do |i,o,e| e.read.empty? ? o.read.chomp("\n") : nil end raise Git::Trac::Error, "Not a git repository" unless @git_dir @git_dir = File.join(".",@git_dir) if @git_dir[0] == ?~ @git_dir = File.(@git_dir) end @options = reload end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(method, *args, &block) ⇒ Object
66 67 68 69 70 71 72 |
# File 'lib/git/trac/repository.rb', line 66 def method_missing(method,*args,&block) if method.to_s =~ /^git_/ exec(method.to_s.tr('_-','-_'),*args, &block) else super(method,*args,&block) end end |
Instance Attribute Details
#git_dir ⇒ Object (readonly)
Returns the value of attribute git_dir.
8 9 10 |
# File 'lib/git/trac/repository.rb', line 8 def git_dir @git_dir end |
#options ⇒ Object (readonly)
Returns the value of attribute options.
8 9 10 |
# File 'lib/git/trac/repository.rb', line 8 def @options end |
Instance Method Details
#agent ⇒ Object
147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 |
# File 'lib/git/trac/repository.rb', line 147 def agent unless defined?(@agent) unless url raise Git::Trac::Error, "missing trac url: consider `git config trac.url http://tracurl`" end require 'mechanize' @agent = WWW::Mechanize.new {|a| a.log = nil} url = "#{url()}/login" if [:password] begin page = @agent.get(url) rescue WWW::Mechanize::ResponseCodeError => e # 401 Forbidden, let's try HTTP authentication raise e unless e.response_code == "401" @agent.basic_auth([:username],[:password]) begin page = @agent.get(url) return @agent rescue WWW::Mechanize::ResponseCodeError => e raise e unless e.response_code == "401" raise Git::Trac::Error, "invalid username or password" end end # Form authentication agent.redirect_ok = false form = page.forms.last form.fields.name("user").value = [:username] form.fields.name("password").value = [:password] form.action = url # Mechanize gets this wrong begin page = @agent.submit(form) unless page.respond_to?(:code) && page.code == "303" raise Git::Trac::Error, "invalid username or password" end ensure agent.redirect_ok = true end end end @agent end |
#cleanup_branches(options, *revs) ⇒ Object
201 202 203 204 205 206 207 208 209 210 211 212 213 214 |
# File 'lib/git/trac/repository.rb', line 201 def cleanup_branches(, *revs) return if revs.empty? diff_hashes = revs.map {|r| diff_hash(r)}.compact if [:rebased] current = current_checkout each_ref("refs/heads") do |object, ref| if current != File.basename(ref) if revs.include?(object) exec("git","branch","-D",File.basename(ref)) elsif diff_hashes && diff_hashes.include?(dh = diff_hash(ref)) exec("git","branch","-D",File.basename(ref)) end end end end |
#config(arg1 = nil, arg2 = nil) ⇒ Object
Parse the output of git-config and return it as a hash.
114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 |
# File 'lib/git/trac/repository.rb', line 114 def config(arg1 = nil, arg2 = nil) unless @config @config = {} exec("git","config","-l") do |line| key, value = line.chomp.split("=",2) superkey, subkey = key.match(/(.*)\.(.*)/).to_a[1,2] @config[superkey] ||= {} @config[superkey][subkey.tr('-_','_-').to_sym] = value # hash[key] ||= [] # hash[key] << value # @config[key] = value end end if arg2 (@config[arg1.to_s]||{})[arg2.to_sym] elsif arg1 @config[arg1] else @config end end |
#current_checkout ⇒ Object
95 96 97 98 99 100 101 102 |
# File 'lib/git/trac/repository.rb', line 95 def current_checkout contents = File.read("#{git_dir}/HEAD").chomp if contents =~ %r{^ref: refs/heads/(.*)} $1 else contents end end |
#diff_hash(head) ⇒ Object
216 217 218 219 220 221 222 223 224 |
# File 'lib/git/trac/repository.rb', line 216 def diff_hash(head) require 'digest/sha1' guess = guess_upstream(head) return unless guess diff = exec("git","diff","#{guess}...#{head}") diff.gsub!(/^(?:index |@@ -).*\n/,'') diff.gsub!(/[[:space:]]/,'') Digest::SHA1.digest(diff) end |
#each_ref(*args) ⇒ Object
88 89 90 91 92 93 |
# File 'lib/git/trac/repository.rb', line 88 def each_ref(*args) pattern = args.empty? ? "refs" : args.join("/") exec("git","for-each-ref", "--format=%(objectname) %(refname)", pattern) do |line| yield *line.chomp.split(" ",2) end end |
#exec(*args, &block) ⇒ Object
Invokes a command. If the command writes to stderr, said output is raised as an exception. Otherwise, read from stdout and return it as a string. If a block is given, each line is yielded to it.
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
# File 'lib/git/trac/repository.rb', line 50 def exec(*args,&block) popen3(*args) do |i,o,e| err = e.read if err.empty? if block_given? o.each_line(&block) nil else o.read end else raise Git::Trac::ExecutionError, err.chomp end end end |
#generated_commits ⇒ Object
A hash of the form => ticket_number
193 194 195 196 197 198 199 |
# File 'lib/git/trac/repository.rb', line 193 def generated_commits hash = {} each_ref("refs/remotes/trac") do |object, ref| hash[object] = File.basename(File.dirname(ref)).to_i end hash end |
#get_response(uri) ⇒ Object
141 142 143 144 145 |
# File 'lib/git/trac/repository.rb', line 141 def get_response(uri) require 'net/http' require 'uri' Net::HTTP.get_response(URI.parse(uri)) end |
#guess_current_ticket_number ⇒ Object
See if the current commit or an ancestor was previously tagged as a trac ticket. Also check git config branch.branchname.tracticket
228 229 230 231 232 233 234 235 236 237 238 |
# File 'lib/git/trac/repository.rb', line 228 def guess_current_ticket_number if number = config("branch.#{current_checkout}", :tracticket) return number.to_i else hash = generated_commits exec("git","rev-list", "--max-count=25", "HEAD") do |line| number = hash[line.chomp] and return number end nil end end |
#guess_upstream(head = "HEAD") ⇒ Object
240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 |
# File 'lib/git/trac/repository.rb', line 240 def guess_upstream(head = "HEAD") svn = config("svn-remote.svn") return unless (svn||{})[:url] branch = popen3("git","log","--no-color",head) do |i,o,e| o.each_line do |line| next unless line.gsub!(/^\s*git-svn-id:\s*/,'') url, uuid = line.chomp.split(" ") url.sub!(/^#{Regexp.escape(svn[:url])}\/*/,'') branch, revision = url.split("@") break branch end end if branch trunk = svn[:trunk] || "trunk:refs/remotes/trunk" branches = svn[:branches] || "branches/*:refs/remotes/*" = svn[:tags] || "tags/*:refs/remotes/tags/*" [trunk, branches, ].each do |pair| remote, local = pair.split(":",2) next if local.to_s.empty? before, after = remote.split("*",2) if branch =~ /^#{Regexp.escape(before)}(.*)#{Regexp.escape(after.to_s)}/ return local.sub(/\*/,$1) end end end nil end |
#in_work_tree(&block) ⇒ Object
Call the block while chdired to the working tree.
36 37 38 |
# File 'lib/git/trac/repository.rb', line 36 def in_work_tree(&block) Dir.chdir(File.dirname(@git_dir),&block) end |
#inspect ⇒ Object
31 32 33 |
# File 'lib/git/trac/repository.rb', line 31 def inspect "#<#{self.class.inspect} #{git_dir} #{url}>" end |
#pager(body, diff = false) ⇒ Object
5 6 7 8 9 10 11 12 |
# File 'lib/git/trac/pager.rb', line 5 def pager(body, diff = false) pager = Pager.new(ENV["GIT_PAGER"] || config("core","pager")) if pager.command diff &&= !%w(false no 0).include?(config("color","pager").to_s.downcase) end diff &&= %w(true yes 1 always auto).include?(config("color","diff").to_s.downcase) pager.page(body, diff) end |
#popen3(*args, &block) ⇒ Object
Open3.popen3 in the current working tree.
41 42 43 44 45 |
# File 'lib/git/trac/repository.rb', line 41 def popen3(*args,&block) args.flatten! cmd = args.shift in_work_tree { Open3.popen3(cmd,*args,&block) } end |
#reload ⇒ Object
:nodoc:
26 27 28 29 |
# File 'lib/git/trac/repository.rb', line 26 def reload #:nodoc: @config = nil @options = (config("trac")||{}).merge(config("trac-remote.trac")||{}).merge(@options) end |
#rev_parse(rev) ⇒ Object
Call git-rev-parse on a revision, returning nil if nothing is found.
75 76 77 78 79 80 81 82 83 84 85 86 |
# File 'lib/git/trac/repository.rb', line 75 def rev_parse(rev) if rev.kind_of?(String) exec("git","rev-parse","--verify",rev).chomp elsif rev.kind_of?(Array) hash = {} return hash if rev.empty? exec("git","rev-parse",*rev) do |rev| hash[name] = rev.chomp if rev.chomp =~ /^[0-9a-f]{40}$/ end hash end end |
#ticket(number) ⇒ Object
Fetch a ticket object by number.
269 270 271 |
# File 'lib/git/trac/repository.rb', line 269 def ticket(number) Ticket.new(self, number) end |
#url ⇒ Object
The trac url associated with the repository.
137 138 139 |
# File 'lib/git/trac/repository.rb', line 137 def url [:url] || config("svn-remote.svn",:url).to_s[%r{(http://.*)/svn},1] end |
#with_index(file) ⇒ Object
104 105 106 107 108 109 110 111 |
# File 'lib/git/trac/repository.rb', line 104 def with_index(file) old_index = ENV["GIT_INDEX_FILE"] ENV["GIT_INDEX_FILE"] = File.join(git_dir,file) yield file ensure ENV["GIT_INDEX_FILE"] = old_index File.unlink(File.join(git_dir,file)) rescue nil end |
#working_tickets ⇒ Object
Return ticket objects for each ticket referenced in the repository.
274 275 276 |
# File 'lib/git/trac/repository.rb', line 274 def working_tickets Dir.entries("#{git_dir}/refs/remotes/trac").map {|number| ticket(number.to_i) unless number.to_i.zero? }.compact end |