From e27d0d9dc1dbdadb44428b041d4736ada85f9ef6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Lemoine?= Date: Fri, 28 Sep 2012 11:23:26 +0200 Subject: [PATCH] Add a tool to create/update the gh-pages branche --- tools/git-update-ghpages | 232 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 232 insertions(+) create mode 100755 tools/git-update-ghpages diff --git a/tools/git-update-ghpages b/tools/git-update-ghpages new file mode 100755 index 0000000000..d4872f3e7c --- /dev/null +++ b/tools/git-update-ghpages @@ -0,0 +1,232 @@ +#!/usr/bin/env ruby +# git update-ghpages user/repo -b gh-pages -p manual/ -i +# +# elemoine +# Modified by me, for +# - https://github.com/rstacruz/git-update-ghpages/issues/1 +# - not failing when there's nothing to commit + +require 'fileutils' +require 'tmpdir' + +module Params + def extract(what) i = index(what) and slice!(i, 2)[1] end; + def first_is(what) shift if what.include?(self.first); end + def self.[](*what) what.extend Params; end + def ===(argv) argv.first_is(self); end +end + +# ============================================================================ + +ARGV.extend Params + +class CLI + # CLI options + attr_reader :prefix #=> "doc/" + attr_reader :input #=> "/home/me/projects/foo" + attr_reader :message #=> "Updated" + attr_reader :repo #=> "git@github.com:me/project.git" + attr_reader :url #=> "http://me.github.com/project" + attr_reader :branch #=> "gh-pages" + + def verbose?() @verbose; end + def force?() @force; end + def simulate?() @simulate; end + + def initialize + # Switches + @verbose = !! (ARGV.extract('--verbose') || ARGV.delete('-v')) + @simulate = !! (ARGV.extract('--simulate') || ARGV.delete('-s')) + @force = !! (ARGV.delete('--force') || ARGV.delete('-f')) + + # Stuff + @prefix = ARGV.extract('--prefix') || ARGV.extract('-p') || '' + @input = File.expand_path(ARGV.extract('--input') || ARGV.extract('-i') || '.') + @message = ARGV.extract('--message') || ARGV.extract('-m') || 'Update' + + # Github info + branch = ARGV.extract('--branch') || ARGV.extract('-b') || nil + @repo, @url, @branch = get_github_info(ARGV.shift, branch) + end + + def git_current_branch + `git rev-parse --abbrev-ref HEAD`.strip + end + + def git_deploy + in_temp_path do |temppath| + status "Cloning repository" + system! "git clone #{repo} -b #{branch} #{temppath}" + + if git_current_branch != branch + status "Warning: No #{branch} branch found in repo, creating one." + return git_deploy_force + end + + copy_files input, File.join(temppath, prefix) + + status "Committing files" + # elemoine - git commit exit code is 1 if there's nothing to commit + #system! "git add .; git add -u; git commit -m #{message.to_s.inspect}" + system! "git add . && git add -u && git commit -m #{message.to_s.inspect}", true + + unless simulate? + status "Updating repo" + system! "git push origin #{branch}" + end + true + end + end + + def git_deploy_force + in_temp_path do |temppath| + status "Creating new repository" + system! "git init ." + system! "git checkout -b gh-pages" + + copy_files input, File.join(temppath, prefix) + + status "Committing files" + # elemoine - git commit exit code is 1 if there's nothing to commit + #system! "git add . && git commit -m #{message.to_s.inspect}" + system! "git add . && git commit -m #{message.to_s.inspect}", true + + unless simulate? + status "Updating repo" + system! "git push #{repo} gh-pages:#{branch} --force" + end + true + end + end + + def get_github_info(repo, branch=nil, prefix=nil) + if github_format?(repo) + user, repo_name = repo.split('/') + r = "git@github.com:#{repo}.git" + + # User page or project page? + if repo_name =~ /\.github\.com/ + [r, "http://#{repo_name}/#{prefix}", branch || 'master' ] + else + [r, "http://#{user}.github.com/#{repo_name}/#{prefix}", branch || 'gh-pages' ] + end + else + [repo, nil, branch] + end + end + + def run! + unless repo + print_help + exit 128 + end + + status "Deploying to #{repo} (branch #{branch})" + msg "NOTE: Running in simulation mode." if simulate? + msg "WARNING: If the repository has gh-pages history, it with be overriden." if force? && !simulate? + + result = force? ? git_deploy_force : git_deploy + + if result + puts "" + status "Done." + msg "See: #{url}" if url && !simulate? + else + tip "Failed." + exit 1 + end + end + + def status(str) + puts "#{c('===>',34)} #{c(str, 32)}" + end + + def msg(str) + puts " #{c(str, 32)}" + end + + def c(str, color) + "\033[#{color}m#{str}\033[0m" + end + + def print_help + tip \ + %{Usage: git update-ghpages username/repository [options] + + Flags: + -f, --force Force an update (WARNING: kills the history!) + -s, --simulate Creates the repository, but doesn't push. + -v, --verbose Verbose mode + + Options: + -p PATH, --prefix The prefix + -i PATH, --input Input (defaults to current directory) + -b BRANCH, --branch The branch to deploy to (defaults to gh-pages) + -m MSG, --message Commit message (defaults to 'Update') + + Examples: + + Update the repo 'coffee' of github user 'james' with the files from the + current directory. The files will be in http://james.github.com/coffee. + + $ git update-ghpages james/coffee + + Same as above, but take the files from 'doc/'. + + $ git update-ghpages james/coffee -i doc + + Same as the first, but the files will instead be in + http://james.github.com/coffee/manual. + + $ git update-ghpages james/coffee -i doc -p manual + }.gsub(/^ {4}/, '') + end + +private # Helpers + + def tip(msg) + $stderr.write "#{msg}\n" + end + + def github_format?(str) + str =~ /^([A-Za-z0-9\-_]+)\/([A-Za-z0-9\-_\.]+)$/ + end + + # Performs actions inside a temp path. + def in_temp_path(&blk) + require 'tmpdir' + Dir.mktmpdir do |dir| + Dir.chdir(dir) { yield dir } + end + end + + # elemoine + # ignoreerr added + def system!(str, ignoreerr=false) + puts `#{str} 2>&1`.strip.gsub(/^/, " ") + raise "Failed with exit code #{$?.to_i}" unless $?.to_i == 0 or ignoreerr == true + end + + # Returns the current branch name + def git_branch + `git symbolic-ref HEAD`.strip.split('/').last + end + + # Copy files from source folder to another + def copy_files(from, to) + status "Copying files #{from} => #{to}..." if verbose? + + Dir["#{from}/**/*"].each do |f| + next unless File.file?(f) + + target = File.join(to, f.gsub(/^#{Regexp.escape from}/, '')) + + FileUtils.mkdir_p File.dirname(target) + msg "%20s => %-20s" % [f, target] if verbose? + FileUtils.cp f, target + end + end + +end + +CLI.new.run!