Class: RIM::GitSession
- Inherits:
-
Object
- Object
- RIM::GitSession
- Defined in:
- lib/rim/git.rb
Defined Under Namespace
Classes: ChangedFile, Status
Instance Attribute Summary collapse
-
#execute_dir ⇒ Object
readonly
Returns the value of attribute execute_dir.
Class Method Summary collapse
Instance Method Summary collapse
-
#all_reachable_non_remote_revs(rev) ⇒ Object
all commits reachable from rev which are not ancestors of remote branches.
-
#changed_files(rev, rev_from = nil) ⇒ Object
returns a list of all files which changed in commit
rev
together with the kind of the change (:modified, :deleted, :added). -
#current_branch ⇒ Object
returns the current branch.
- #current_branch_name ⇒ Object
- #execute(cmd) ⇒ Object
-
#export_rev(rev, dir, paths = []) ⇒ Object
export file contents of rev to dir if
paths
is given and non-empty, checks out only those parts of the filesystem tree does not remove any files from dir which existed before. -
#git_version ⇒ Object
3 most significant numbers of git version of nil if it can’t be determined.
-
#has_branch?(branch) ⇒ Boolean
check whether branch exists.
-
#has_remote_branch?(branch) ⇒ Boolean
check whether remote branch exists.
-
#has_valid_remote_repository? ⇒ Boolean
check whether remote repository is valid.
-
#initialize(logger, execute_dir, arg = {}) ⇒ GitSession
constructor
A new instance of GitSession.
-
#is_ancestor?(ancestor, child) ⇒ Boolean
checks whether the first (ancestor) revision is is ancestor of the second (child) revision.
-
#parent_revs(rev) ⇒ Object
returns the parent commits of rev as SHA-1s returns an empty array if there are no parents (e.g. orphan or initial).
-
#remote_branch_revs ⇒ Object
returns the SHA-1 representations of the heads of all remote branches.
-
#rev_sha1(rev) ⇒ Object
returns the SHA-1 representation of rev.
- #status(dir = nil) ⇒ Object
- #uncommited_changes? ⇒ Boolean
-
#within_exported_rev(rev, paths = []) ⇒ Object
checks out rev to a temporary directory and yields this directory to the given block if
paths
is given and non-empty, checks out only those parts of the filesystem tree returns the value returned by the block.
Constructor Details
#initialize(logger, execute_dir, arg = {}) ⇒ GitSession
Returns a new instance of GitSession.
21 22 23 24 25 26 27 28 |
# File 'lib/rim/git.rb', line 21 def initialize(logger, execute_dir, arg = {}) @execute_dir = execute_dir if arg.is_a?(Hash) @work_dir = arg.has_key?(:work_dir) ? arg[:work_dir] : "" @git_dir = arg.has_key?(:git_dir) ? arg[:git_dir] : "" end @logger = logger end |
Instance Attribute Details
#execute_dir ⇒ Object (readonly)
Returns the value of attribute execute_dir.
19 20 21 |
# File 'lib/rim/git.rb', line 19 def execute_dir @execute_dir end |
Class Method Details
.logger=(logger) ⇒ Object
30 31 32 |
# File 'lib/rim/git.rb', line 30 def self.logger=(logger) @logger = logger end |
.next_invocation_id ⇒ Object
39 40 41 42 |
# File 'lib/rim/git.rb', line 39 def self.next_invocation_id @invocation_id ||= 0 @invocation_id += 1 end |
.open(execute_dir, options = {}) ⇒ Object
34 35 36 37 |
# File 'lib/rim/git.rb', line 34 def self.open(execute_dir, = {}) log = @logger || Logger.new($stdout) self.new(log, execute_dir, ) end |
Instance Method Details
#all_reachable_non_remote_revs(rev) ⇒ Object
all commits reachable from rev which are not ancestors of remote branches
161 162 163 164 |
# File 'lib/rim/git.rb', line 161 def all_reachable_non_remote_revs(rev) out = execute "git rev-list #{rev} --not --remotes --" out.split("\n") end |
#changed_files(rev, rev_from = nil) ⇒ Object
returns a list of all files which changed in commit rev
together with the kind of the change (:modified, :deleted, :added)
if from_rev
is given, lists changes between +from_rev and rev
with one argument only, no changes will be returned for merge commits use the two argument variant for merge commits and decide for one parent
232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 |
# File 'lib/rim/git.rb', line 232 def changed_files(rev, rev_from=nil) out = execute "git diff-tree -r --no-commit-id #{rev_from} #{rev}" out.split("\n").collect do |l| cols = l.split path = cols[5] kind = case cols[4] when "M" :modified when "A" :added when "D" :deleted else nil end ChangedFile.new(path, kind) end end |
#current_branch ⇒ Object
returns the current branch
92 93 94 95 96 97 98 99 100 |
# File 'lib/rim/git.rb', line 92 def current_branch out = execute "git branch" out.split("\n").each do |l| if l =~ /^\*\s+(\S+)/ return $1 end end nil end |
#current_branch_name ⇒ Object
219 220 221 222 |
# File 'lib/rim/git.rb', line 219 def current_branch_name out = execute "git rev-parse --abbrev-ref HEAD" out.strip end |
#execute(cmd) ⇒ Object
268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 |
# File 'lib/rim/git.rb', line 268 def execute(cmd) raise "git command has to start with 'git'" unless cmd.start_with? "git " cmd.slice!("git ") # remove any newlines as they will cause the command line to end prematurely cmd.gsub!("\n", "") = ((!@execute_dir || @execute_dir == ".") ? "" : " -C #{@execute_dir}") \ + (@work_dir.empty? ? "" : " --work-tree=#{File.(@work_dir)}") \ + (@git_dir.empty? ? "" : " --git-dir=#{File.(@git_dir)}") cmd = "git#{} #{cmd} 2>&1" out = `#{cmd}` # make sure we don't run into any encoding misinterpretation issues out.force_encoding("binary") exitstatus = $?.exitstatus invid = self.class.next_invocation_id.to_s.ljust(4) @logger.debug "git##{invid} \"#{cmd}\" => #{exitstatus}" out.split(/\r?\n/).each do |ol| @logger.debug "git##{invid} out : #{ol}" end exception = exitstatus != 0 ? GitException.new(cmd, exitstatus, out) : nil if block_given? yield out, exception elsif exception raise exception end out end |
#export_rev(rev, dir, paths = []) ⇒ Object
export file contents of rev to dir if paths
is given and non-empty, checks out only those parts of the filesystem tree does not remove any files from dir which existed before
169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 |
# File 'lib/rim/git.rb', line 169 def export_rev(rev, dir, paths=[]) paths = paths.dup loop do path_args = "" # max command line length on Windows XP and higher is 8191 # consider the following extra characters which will be added: # up to 3 paths in execute, 1 path for tar, max path length 260 = 1040 # plus some "glue" characters, plus the last path item with 260 max; # use 6000 to be on the safe side while !paths.empty? && path_args.size < 6000 path_args << " " path_args << paths.shift end execute "git archive --format tar #{rev} #{path_args} | tar -x -C #{dir}" break if paths.empty? end end |
#git_version ⇒ Object
3 most significant numbers of git version of nil if it can’t be determined
252 253 254 255 256 257 258 259 |
# File 'lib/rim/git.rb', line 252 def git_version out = execute("git --version") if out =~ /^git version (\d+\.\d+\.\d+)/ $1 else nil end end |
#has_branch?(branch) ⇒ Boolean
check whether branch exists
103 104 105 106 107 |
# File 'lib/rim/git.rb', line 103 def has_branch?(branch) execute("git show-ref refs/heads/#{branch}") do |b, e| return !e end end |
#has_remote_branch?(branch) ⇒ Boolean
check whether remote branch exists
110 111 112 113 114 115 116 |
# File 'lib/rim/git.rb', line 110 def has_remote_branch?(branch) out = execute("git ls-remote --heads") out.split("\n").each do |l| return true if l.split(/\s+/)[1] == "refs/heads/#{branch}" end false end |
#has_valid_remote_repository? ⇒ Boolean
check whether remote repository is valid
119 120 121 122 123 |
# File 'lib/rim/git.rb', line 119 def has_valid_remote_repository?() execute("git ls-remote") do |b, e| return !e end end |
#is_ancestor?(ancestor, child) ⇒ Boolean
checks whether the first (ancestor) revision is is ancestor of the second (child) revision
126 127 128 129 130 |
# File 'lib/rim/git.rb', line 126 def is_ancestor?(ancestor, child) execute("git merge-base --is-ancestor #{ancestor} #{child}") do |b, e| return !e end end |
#parent_revs(rev) ⇒ Object
returns the parent commits of rev as SHA-1s returns an empty array if there are no parents (e.g. orphan or initial)
134 135 136 137 |
# File 'lib/rim/git.rb', line 134 def parent_revs(rev) out = execute "git rev-list -n 1 --parents #{rev} --" out.strip.split[1..-1] end |
#remote_branch_revs ⇒ Object
returns the SHA-1 representations of the heads of all remote branches
149 150 151 152 153 154 155 156 157 158 |
# File 'lib/rim/git.rb', line 149 def remote_branch_revs out = execute "git show-ref" out.split("\n").collect { |l| if l =~ /refs\/remotes\// l.split[0] else nil end }.compact end |
#rev_sha1(rev) ⇒ Object
returns the SHA-1 representation of rev
140 141 142 143 144 145 146 |
# File 'lib/rim/git.rb', line 140 def rev_sha1(rev) sha1 = nil execute "git rev-list -n 1 #{rev} --" do |out, e| sha1 = out.strip if !e end sha1 end |
#status(dir = nil) ⇒ Object
261 262 263 264 265 266 |
# File 'lib/rim/git.rb', line 261 def status(dir = nil) # -s short format # --ignored show ignored out = execute "git status -s --ignored #{dir}" parse_status(out) end |
#uncommited_changes? ⇒ Boolean
214 215 216 217 |
# File 'lib/rim/git.rb', line 214 def uncommited_changes? # either no status lines are all of them due to ignored items !status.lines.all?{|l| l.ignored?} end |
#within_exported_rev(rev, paths = []) ⇒ Object
checks out rev to a temporary directory and yields this directory to the given block if paths
is given and non-empty, checks out only those parts of the filesystem tree returns the value returned by the block
190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 |
# File 'lib/rim/git.rb', line 190 def within_exported_rev(rev, paths=[]) Dir.mktmpdir("rim") do |d| c = File.join(d, "content") FileUtils.mkdir(c) export_rev(rev, c, paths) # return contents of yielded block # mktmpdir returns value return by our block yield c FileUtils.rm_rf(c) # retry to delete if it hasn't been deleted yet # this could be due to Windows keeping the files locked for some time # this is especially a problem if the machine is at its limits retries = 600 while File.exist?(c) && retries > 0 sleep(0.1) FileUtils.rm_rf(c) retries -= 1 end if File.exist?(c) @logger.warn "could not delete temp dir: #{c}" end end end |