Skip to content

Instantly share code, notes, and snippets.

@ollie
Created October 30, 2014 10:50
Show Gist options
  • Save ollie/e79c3cd0779ac4f54913 to your computer and use it in GitHub Desktop.
Save ollie/e79c3cd0779ac4f54913 to your computer and use it in GitHub Desktop.
Multithreaded Ruby "git pull".
#!/usr/bin/env ruby
require 'pathname'
require 'open3'
# Mass-pull git repositories.
#
# GitPull.mass_pull(Dir.pwd)
class GitPull
# Check for this string in directory names.
GIT_DIR = '.git'
# Recursively crawl down the +directory+ and +git pull+ it if it's
# a Git repo. Shortcut method for creating an instance.
#
# @param directory [String, Pathname]
def self.mass_pull(directory)
new.mass_pull(Pathname.new(directory))
end
# Setup threads array.
def initialize
@threads = []
end
# Recursively crawl down the +directory+ and +git pull+ it if it's
# a Git repo. Waits for all threads to finish.
#
# @param directory [Pathname]
def mass_pull(directory)
crawl(directory)
@threads.each(&:join)
end
# Recursively crawl down the +directory+ and +git pull+ it if it's
# a Git repo. Adds threads and does not wait.
#
# @param directory [Pathname]
def crawl(directory)
subdirectories = list_directories(directory)
if git?(subdirectories)
@threads << Thread.new do
pull(directory)
end
else
subdirectories.each do |subdirectory|
crawl(subdirectory)
end
end
end
# List all relevant subdirectories in +directory+.
#
# @param directory [Pathname]
def list_directories(directory)
directory.children.select(&:directory?)
end
# Is there a +.git+ directory among the subdirectories?
#
# @param subdirectories [Array<Pathname>]
#
# @return [Bool]
def git?(subdirectories)
subdirectories.find do |directory|
directory_name = directory.basename.to_s
directory_name == GIT_DIR
end
end
# Create a new process which updates the repository.
# Process is needed because +Dir.chdir+ is not thread-safe.
def pull(directory)
command = "cd #{ directory } && git pull"
puts command
out, _ = Open3.capture2(command)
puts out
end
end
# Do it!
GitPull.mass_pull(Dir.pwd)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment