Module: GitHelpers::GitBranchInfos
- Included in:
- GitDir
- Defined in:
- lib/git_helpers/branch_infos.rb
Overview
more infos on branches
Instance Method Summary collapse
- #ahead_behind(br1, br2) ⇒ Object
- #branch_infos(*branches, local: false, remote: false, tags: false, merged: nil, no_merged: nil) ⇒ Object
- #format_branch_infos(infos, compare: nil, merged: nil, cherry: false, log: false) ⇒ Object
- #name(branch = 'HEAD', **args) ⇒ Object
- #name_branch(branch = 'HEAD', **args) ⇒ Object
-
#recursive_upstream(*branches, local: true) ⇒ Object
return all local upstreams of branches, recursively.
Instance Method Details
#ahead_behind(br1, br2) ⇒ Object
4 5 6 7 8 9 10 11 12 |
# File 'lib/git_helpers/branch_infos.rb', line 4 def ahead_behind(br1, br2) with_dir do out=run_simple("git rev-list --left-right --count #{br1.shellescape}...#{br2.shellescape}", error: :quiet) out.match(/(\d+)\s+(\d+)/) do |m| return m[1].to_i, m[2].to_i #br1 is ahead by m[1], behind by m[2] from br2 end return 0, 0 end end |
#branch_infos(*branches, local: false, remote: false, tags: false, merged: nil, no_merged: nil) ⇒ Object
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 |
# File 'lib/git_helpers/branch_infos.rb', line 14 def branch_infos(*branches, local: false, remote: false, tags: false, merged: nil, no_merged: nil) query = [] query << "--merged=#{merged.shellescape}" if merged query << "--no_merged=#{no_merged.shellescape}" if no_merged query += branches.map {|b| name_branch(b)} query << 'refs/heads' if local query << 'refs/remotes' if remote query << 'refs/tags' if r={} format=%w(refname refname:short objecttype objectsize objectname upstream upstream:short upstream:track upstream:remotename upstream:remoteref push push:short push:track push:remotename push:remoteref HEAD symref) #Note push:remoteref is buggy (empty if no push refspec specified) #and push:track is upstream:track (cf my patch to the git mailing #list to correct that) out=run_simple("git for-each-ref --format '#{format.map {|f| "%(#{f})"}.join(';')}' #{query.shelljoin}", chomp: :lines) out.each do |l| infos=l.split(';') full_name=infos[0] infos=Hash[format.zip(infos)] infos[:name]=infos["refname:short"] infos[:head]=!(infos["HEAD"].empty? or infos["HEAD"]==" ") type=if full_name.start_with?("refs/heads/") :local elsif full_name.start_with?("refs/remotes/") :remote elsif full_name.start_with?("refs/tags/") :tags end name = case type when :local full_name.delete_prefix("refs/heads/") when :remote full_name.delete_prefix("refs/remotes/") when :tags full_name.delete_prefix("refs/tags/") end infos[:type]=type infos[:name]=name infos[:upstream_ahead]=0 infos[:upstream_behind]=0 infos[:push_ahead]=0 infos[:push_behind]=0 track=infos["upstream:track"] track.match(/ahead (\d+)/) do |m| infos[:upstream_ahead]=m[1].to_i end track.match(/behind (\d+)/) do |m| infos[:upstream_behind]=m[1].to_i end ## git has a bug for push:track # ptrack=infos["push:track"] # ptrack.match(/ahead (\d+)/) do |m| # infos[:push_ahead]=m[1].to_i # end # ptrack.match(/behind (\d+)/) do |m| # infos[:push_behind]=m[1].to_i # end unless infos["push"].empty? ahead, behind=ahead_behind(infos["refname"], infos["push"]) infos[:push_ahead]=ahead infos[:push_behind]=behind end origin = infos["upstream:remotename"] unless origin.empty? upstream_short=infos["upstream:short"] infos["upstream:name"]=upstream_short.delete_prefix(origin+"/") end pushorigin = infos["push:remotename"] unless pushorigin.empty? push_short=infos["push:short"] if push_short.empty? infos["push:name"]=infos["refname:short"] else infos["push:name"]= push_short.delete_prefix(pushorigin+"/") end end r[full_name]=infos end r end |
#format_branch_infos(infos, compare: nil, merged: nil, cherry: false, log: false) ⇒ Object
100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 |
# File 'lib/git_helpers/branch_infos.rb', line 100 def format_branch_infos(infos, compare: nil, merged: nil, cherry: false, log: false) # warning, here we pass the info values, ie infos should be a list infos.each do |i| name=i["refname:short"] upstream=i["upstream:short"] push=i["push:short"] color=:magenta if merged color=:red #not merged [*merged].each do |br| ahead, _behind=ahead_behind(i["refname"], br) if ahead==0 color=:magenta break end end end r="#{i["HEAD"]}#{name.color(color)}" if compare ahead, behind=ahead_behind(i["refname"], compare) r << "↑#{ahead}" unless ahead==0 r << "↓#{behind}" unless behind==0 end unless upstream.empty? r << " @{u}" r << "=@{push}" if push==upstream r << "=#{upstream.color(:yellow)}" r << "↑#{i[:upstream_ahead]}" unless i[:upstream_ahead]==0 r << "↓#{i[:upstream_behind]}" unless i[:upstream_behind]==0 end unless push.empty? or push == upstream r << " @{push}=#{push.color(:yellow)}" r << "↑#{i[:push_ahead]}" unless i[:push_ahead]==0 r << "↓#{i[:push_behind]}" unless i[:push_behind]==0 end if log =case log when Hash log.map {|k,v| "--#{k}=#{v.shellescape}"}.join(' ') when String log else "" end r << " → "+run_simple("git -c color.ui=always log --date=human --oneline --no-walk #{} #{name}") end puts r if cherry #todo: add push cherry? if upstream and i[:upstream_ahead] != 0 || i[:upstream_behind] != 0 ch=run_simple("git -c color.ui=always log --left-right --topo-order --oneline #{name}...#{upstream}") ch.each_line do |l| puts " #{l}" end end end end end |
#name(branch = 'HEAD', **args) ⇒ Object
161 162 163 |
# File 'lib/git_helpers/branch_infos.rb', line 161 def name(branch='HEAD',**args) self.branch(branch).name(**args) end |
#name_branch(branch = 'HEAD', **args) ⇒ Object
158 159 160 |
# File 'lib/git_helpers/branch_infos.rb', line 158 def name_branch(branch='HEAD',**args) self.branch(branch).full_name(**args) end |
#recursive_upstream(*branches, local: true) ⇒ Object
return all local upstreams of branches, recursively
166 167 168 169 170 171 172 173 174 175 176 |
# File 'lib/git_helpers/branch_infos.rb', line 166 def recursive_upstream(*branches, local: true) require 'tsort' each_node=lambda do |&b| branches.each(&b) end each_child=lambda do |br, &b| upstream=branch(br).upstream(short: false) upstreams=[] upstreams << upstream.to_s unless upstream.nil? or local && upstream.to_s.start_with?("refs/remotes/") upstreams.each(&b) end TSort.tsort(each_node, each_child) end |