Git pull multiple local repositories with script (ruby?) - ruby

I have ~30 git repositories cloned from github that I use for web/ruby/javascript development. Is it possible to bulk update all of them with a script?
I have everything pretty organized (folder structure):
- Workspace
- Android
- Chrome
- GitClones
- Bootstrap
~ etc...30 some repositories
- iPhone
- osx
- WebDev
I have a ruby script to clone repositories with octokit, but are there any suggestions on how to do git pull (overwriting/rebasing local) in all the repositories under GitClones?
Normally I would just do a pull whenever I was about to use that repo, but I am going to a place where internet connectivity is only going to be available sometimes. So I would like to update everything I can while I have internet.
Thanks! (Running osx 10.8.2)

If you must do it in Ruby, here's a quick and dirty script:
#!/usr/bin/env ruby
Dir.entries('./').select do |entry|
next if %w{. .. ,,}.include? entry
if File.directory? File.join('./', entry)
cmd = "cd #{entry} && git pull"
`#{cmd}`
end
end
Don't forget to chmod +x the file you copy this into and ensure it's in your GitClones directory.

Sure, but why use ruby when shell will suffice?
function update_all() {
for dir in GitClones/*; do
cd "$dir" && git pull
done
}

Change beginning of glob to taste. This does two useful things:
It only git pull when it contains .git subdir
It skips dot (.) dirs since no one has git repos which start with a dot.
Enjoy
# Assumes run from Workspace
Dir['GitClones/[^.]*'].select {|e| File.directory? e }.each do |e|
Dir.chdir(e) { `git pull` } if File.exist? File.join(e, '.git')
end

Revised to provider better output and be OS agnostic. This one cleans local changes, and updates code.
#!/usr/bin/env ruby
require 'pp'
# no stdout buffering
STDOUT.sync = true
# checks for windows/unix for chaining commands
OS_COMMAND_CHAIN = RUBY_PLATFORM =~ /mswin|mingw|cygwin/ ? "&" : ";"
Dir.entries('.').select do |entry|
next if %w{. .. ,,}.include? entry
if File.directory? File.join('.', entry)
if File.directory? File.join('.', entry, '.git')
full_path = "#{Dir.pwd}/#{entry}"
git_dir = "--git-dir=#{full_path}/.git --work-tree=#{full_path}"
puts "\nUPDATING '#{full_path}' \n\n"
puts `git #{git_dir} clean -f #{OS_COMMAND_CHAIN} git #{git_dir} checkout . #{OS_COMMAND_CHAIN} git #{git_dir} pull`
end
end
end

Related

(SOLVED) Why doesn't the Ruby Git gem see my variables?

I'm building a simple utility for cloning down git repositories of other ruby programs my company has built, then install and configure them.
So, I'm very new to Ruby, so I apologize if this is a super noob question.
But I have a class that handles creating the directories it needs and cloning the repo, but it's returning this error when I run the code, and I don't know why...
This is the error:
Cloning the requested Git Repository now!
-----------------------------------------
C:/Ruby31-x64/lib/ruby/gems/3.1.0/gems/git-1.12.0/lib/git/lib.rb:1125:in `command': git "-c" "core.quotePath=true"
"-c" "color.ui=false" clone "--" "" "{:path=>\\"\\", :bare=>true}" 2>&1:fatal: The empty string is not a valid path (Git::GitExecuteError)
from C:/Ruby31-x64/lib/ruby/gems/3.1.0/gems/git-1.12.0/lib/git/lib.rb:116:in `clone'
from C:/Ruby31-x64/lib/ruby/gems/3.1.0/gems/git-1.12.0/lib/git/base.rb:21:in `clone'
from C:/Ruby31-x64/lib/ruby/gems/3.1.0/gems/git-1.12.0/lib/git.rb:176:in `clone'
from C:/Users/conno/OneDrive/Desktop/Ruby Installer/Pixelated-Ruby-Installer/classes/Gitclone.rb:43:in `clone'
from ./starter.rb:48:in `<main>'
This is my code (again, remember I am very new. So literally any and all advice is helpful):
#!/bin/ruby
# class declaration
class Gitclone
require "fileutils"
require "git"
require "rubygems"
# attribute reader so other classes/methods can read the vars in this class
attr_reader :giturl, :destpa
# init class method to set instance variables for giturl and destination path
def initialize(giturl, destpa)
#giturl = giturl
#destpa = destpa
end
# class method to create directories and clone git repositories
def self.clone
# I don't think this needs to be here. It was added for the sake of seeing if it would fix the issue
giturl = #giturl
destpa = #destpa
# see last comment about the above 2 lines
puts "Creating directories!"
21.times {
print "-"
}
puts ""
sleep(2)
# right now, this is hardcoded. I should probably make it it's own method we can call...
# it creates new directories
FileUtils.mkdir_p "/etc/pixelated/ruby/bin"
puts "We have created the /etc/pixelated/ruby/bin directory!"
54.times {
print "-"
}
puts ""
sleep(2)
puts "Cloning the requested Git Repository now!"
41.times {
print "-"
}
puts ""
sleep(2)
# this bit here simply uses the Git gem to clone the repository URL stored in the 'giturl' instance variable to the path stored in the 'destpa' instance variable
git = Git.clone("#{giturl}", path: "#{destpa}", bare: true)
# notify the user if the repository was cloned successfuly
if Dir.exist?("/etc/pixelated/ruby/bin/$softtype")
then
puts "Successfully Cloned the Repo!"
puts ""
else
puts "ERROR! Repo was not cloned! Did you give us the right link?"
puts ""
end
end
end
I did declare the variables that I'm using, yet it apparently thinks they haven't?
I am almost certain that this is my noob brain using variable wrong...
Can someone offer me some guidance please?
EDIT: I may have answered my own question. I realized I'm booted into my Windows OS, not Arch Linux, and my code is using Linux paths, not Windows paths. Gonna put it up on one of my ubuntu servers and see if it works there.

Implement git branch --contains with rugged library

I'm working with a ruby script that execute the following git command on a given git repository.
branches = `git branch -a --contains #{tag_name}`
This approach has some drawbacks with command output (that may change in different git versions) and is subject to git binary version on the hosting machine, so I was trying to see if it's possible to replace that command using rugged but I wasn't able to find anything similar to that.
Maybe in rugged there's no way to implement --contains flag, but I think it should be pretty easy to implement this behavior:
Given any git commit-ish (a tag, a commit sha, etc.) how to get (with rugged) the list of branches (both local and remote) that contains that commit-ish?
I need to implement something like github commit show page, i.e. tag xyz is contained in master, develop, branch_xx
Finally solved with this code:
def branches_for_tag(tag_name, repo_path = Dir.pwd)
#branches ||= begin
repo = Rugged::Repository.new(repo_path)
# Convert tag to sha1 if matching tag found
full_sha = repo.tags[tag_name] ? repo.tags[tag_name].target_id : tag_name
logger.debug "Inspecting repo at #{repo.path}, branches are #{repo.branches.map(&:name)}"
# descendant_of? does not return true for it self, i.e. repo.descendant_of?(x, x) will return false for every commit
# #see https://github.com/libgit2/libgit2/pull/4362
repo.branches.select { |branch| repo.descendant_of?(branch.target_id, full_sha) || full_sha == branch.target_id }
end
end

GIT post-receive multiple branch deployment

I have a development and production folder on the same server and 1 repo behind them to push to both folders depending on the branch that is pushed. I would like the development folder to be deployed to when develop is pushed to the repo and the production folder when master is pushed. I have an edited ruby post-receive file I found on a different site but I am new to ruby and can't seem to figure out why it isn't pushing to either folder.
#!/usr/bin/env ruby
# post-receive
from, to, branch = ARGF.read.split " "
if (branch =~ /^master/)
puts "Received branch #{branch}, deploying to production."
deploy_to_dir = File.expand_path('/var/www/html/production')
`GIT_WORK_TREE="#{deploy_to_dir}" git checkout -f master`
puts "DEPLOY: master(#{to}) copied to '#{deploy_to_dir}'"
exit
∂
elsif (branch =~ /^develop/)
puts "Received branch #{branch}, deploying to development."
deploy_to_dir = File.expand_path('/var/www/html/development')
`GIT_WORK_TREE="#{deploy_to_dir}" git checkout -f develop`
puts "DEPLOY: develop(#{to}) copied to '#{deploy_to_dir}'"
exit
end
Any help on this post-receive or a replacement would be appreciated.
If you don't mind shell script instead of Ruby then these people have solved the same problem.
Git post-receive hook to checkout each branch to different folders?
Perhaps a little late to the party on this, however maybe it will help others that are trying to find a solution in Ruby. Here is a working example (modified from this source which got me sorted):
#!/usr/bin/env ruby
# post-receive
# 1. Read STDIN (Format: "from_commit to_commit branch_name")
from, to, branch = ARGF.read.split " "
# 2. Only deploy if staging or master branch was pushed
if (branch =~ /staging$/) == nil && (branch =~ /master$/) == nil
puts "Received branch #{branch}, not deploying."
exit
end
# 3. Copy files to deploy directory(Path to deploy is relative to the git bare repo: e.g. website-root/repos)
if (branch =~ /staging$/)
deploy_to_dir = File.expand_path('../path-to-staging-deploy.com')
`GIT_WORK_TREE="#{deploy_to_dir}" git checkout -f staging`
puts "DEPLOY: staging(#{to}) copied to '#{deploy_to_dir}'"
elsif (branch =~ /master$/)
deploy_to_dir = File.expand_path('../path-to-master-deploy.com')
`GIT_WORK_TREE="#{deploy_to_dir}" git checkout -f master`
puts "DEPLOY: master(#{to}) copied to '#{deploy_to_dir}'"
else
puts "Received branch #{branch}, not deploying."
exit
end
I'm new to Ruby so there is probably a better way to write this, but it is working as expected - as far as I can see.

Running ruby code on cucumber

I'm new to cucumber and I just found out Before hooks.
I'm already doing this on minitest/spec.
I want to create a git repository before any scenario and destroy it after.
this is what I have:
Before do
require 'tmpdir'
#directory = Dir.mktmpdir('temp-repo')
#orig_directory = Dir.pwd
Dir.chdir(#directory)
`git init`
`touch dummy`
`git add .`
`git commit -m 'dummy commit'`
end
After do
Dir.chdir(#orig_directory)
FileUtils.rmtree(#directory)
end
But when i run cucumber it fails with this message:
Lexing error on line 6: ' #directory = Dir.mktmpdir('temp-repo')'
I already looked into the wiki and some other questions here but can't figure out how to get that working.
The hooks should be registered in the support files (for example features/support/env.rb) not in your features.
It's stated in the second sentence of the wiki.

Check if a git branch exists in the local repository with ruby?

What would be the best way of checking if git branch exists in the local git repository with ruby? My ruby skills are not that good, so would like to know the best way of going about it :) Thanks.
There are ruby libraries for accessing git repositories, one being grit.
To install use [sudo] gem install grit.
$ irb
>> require 'grit'
=> true
>> repo = Grit::Repo.new('/path/to/your/repo/')
=> #<Grit::Repo "/path/to/your/repo/.git">
>> repo.branches
=> [#<Grit::Head "master">, #<Grit::Head "some-topic-branch">, ...]
I ended up coming up with this:
# Check if a Branch Exists
def branch_exists(branch)
branches = run("git branch",false)
regex = Regexp.new('[\\n\\s\\*]+' + Regexp.escape(branch.to_s) + '\\n')
result = ((branches =~ regex) ? true : false)
return result
end
Where run is a backtick expression. The reasoning is that the code is to be highly portable and is not allowed any other dependencies. Whereas git is installed in the environment.

Resources