# The MIT License # Copyright © 2009 Magnus Bergmark # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. class GitRemoteMonitor::GitWrapper class << self def local_branch branches = call_get_local_branch.split("\n") current = branches.detect { |branch| branch.strip.include? "* " } return nil unless current current.strip.slice(/^\* (.+)$/, 1) end def remote_branch branch = self.local_branch remote = call_get_remote(branch).strip return nil if remote.empty? "#{remote}/#{branch}" end def get_tracking_info(our_branch, their_branch) tracking_info = call_get_tracking_info(our_branch, their_branch).split("\n") if tracking_info.size > 2 raise "Wrong number of lines returned while trying to look at tracking information!" elsif tracking_info.size == 2 return [*tracking_info.collect { |line| line.gsub(/\D+/, '').to_i }] else # We have too look at which kind it is tracking_info = tracking_info.first if tracking_info and tracking_info.include? "<" return [tracking_info.gsub(/\D+/, '').to_i, 0] elsif tracking_info and tracking_info.include? ">" return [0, tracking_info.gsub(/\D+/, '').to_i] else return [0, 0] end end end # # Calls "git fetch" on the current working directory. Raises an error in case this # command ran unsuccessfully. # # The method will return true if a fetch was made or false if nothing was fetched. # def fetch! raise "This repository have no remotes to fetch from!" unless has_remotes? # If the output was empty, no actual fetch was done return !call_fetch.strip.empty? end # # Returns number of defined remotes or nil if no remotes are defined. Useful for # if statements before doing fetches and whatnot. # # Works on current working dir, like most of the methods here. # def has_remotes? remotes = call_remotes_list.strip.split("\n").size return nil if remotes == 0 remotes end # # Returns true if current working dir is inside a git repository. False otherwise. # def in_repo? call_repo_discovery end protected # Do the actual system call for "git fetch", returning output def call_fetch output = `git fetch 2>&1` raise "Could not fetch from remote! " + output unless $?.success? output end # Asks Git about tracking information for the given local branch and the specified # remote branch. # # Returns output formatted by `uniq -c` after looking at a list of commits # It should contain between 1 and 2 lines inclusive and look like this: # 4 < # 1 > # # * The lines will be indented by spaces, then have a number, a space and a symbol. # * When no branch have moved, the output will be on 1 line and have a 1 as the number # and no symbol. # * The symbols mean the following: "<" means local commits, ">" means remote commits def call_get_tracking_info(our, their) `git rev-list --left-right #{our}...#{their} | cut -c 1 | sort | uniq -c` end def call_get_local_branch `git branch --no-color` end def call_get_remote(local_name) `git config branch.#{local_name}.remote` end def call_remotes_list `git branch -r --no-color` end # Runs a simple plumbing command to quickly see if there is a repository in current working dir. # Returns true or false depending on success in calling the command. def call_repo_discovery `git show-ref` $?.success? end end end