Last active
March 3, 2019 02:14
-
-
Save tmtm/10392069 to your computer and use it in GitHub Desktop.
Postfix の tarball から Git リポジトリを作るスクリプト
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- coding: utf-8 -*- | |
# Postfix はソースが公開されてはいるもののリポジトリが公開されていない | |
# ので、公開されている tarball から git リポジトリを作るためのスクリプ | |
# トを作ってみました。 | |
# | |
# 次の場所から、postfix-*.tar.gz を持ってきて、どっかに置いておきます。 | |
# * ftp://ftp.porcupine.org/mirrors/project-history/postfix/official/ | |
# * ftp://ftp.porcupine.org/mirrors/postfix-release/official/ | |
# tar.gz ファイルの日付の古い順に処理するので、ファイルの日付までコピー | |
# できるツールを使って取得ください。 | |
# | |
# 例: | |
# wget -nc -r -nH --cut-dirs=4 ftp://ftp.porcupine.org/mirrors/project-history/postfix/official/postfix-\*.tar.gz | |
# wget -nc -r -nH --cut-dirs=3 ftp://ftp.porcupine.org/mirrors/postfix-release/official/postfix-\*.tar.gz | |
# | |
# 第一引数に tar.gz を置いたディレクトリ、第二引数に作成する Git リポジ | |
# トリのパスを指定してこのスクリプトを実行すると Git リポジトリを作成し | |
# ます。第二引数のリポジトリが存在しない場合は自動的に作成するので、存 | |
# 在しないディレクトリを指定すればOKです。 | |
require 'tempfile' | |
require 'tmpdir' | |
require 'date' | |
class Version | |
attr_reader :str | |
attr_reader :ver | |
def initialize(str) | |
if str =~ /\.tar\.gz\z/ | |
@str = File.basename(str, '.tar.gz').split(/-/, 2).last | |
else | |
@str = str | |
end | |
if @str =~ /\A\d{8}/ | |
@ver = [0, 0, 0, 0, @str] | |
else | |
@ver = @str.split(/\./).map{|_| _ =~ /\A\d+\z/ ? _.to_i : _} | |
end | |
end | |
def ==(other) | |
@ver == other.ver | |
end | |
def <(other) | |
(@ver <=> other.ver) < 0 | |
end | |
def >(other) | |
(@ver <=> other.ver) > 0 | |
end | |
def <=>(other) | |
@ver <=> other.ver | |
end | |
def branch_name | |
@ver.first(2).join('.') | |
end | |
end | |
def system!(*args) | |
puts args.join(' ') if $VERBOSE | |
system(*args) or raise "#{args.first}: failed" | |
end | |
class Git | |
def initialize(repos) | |
@repos = repos | |
unless File.exist? repos | |
init | |
initial_commit | |
end | |
end | |
def init | |
command '--bare', 'init' | |
end | |
def initial_commit | |
Dir.mktmpdir do |tmpdir| | |
command '--bare', '--work-tree', tmpdir, 'commit', '--allow-empty', '-m' 'Initial commit' | |
end | |
end | |
def create_branch(new, src) | |
puts "create branch #{new} from #{src}" | |
command 'branch', new, src | |
end | |
def change_current_branch(branch) | |
puts "change to #{branch}" | |
Dir.mktmpdir do |dir| | |
command '--work-tree', dir, 'checkout', '-q', branch | |
end | |
end | |
def tags | |
`git --git-dir #{@repos} tag`.lines.map(&:chomp) | |
end | |
def command(*args) | |
system! 'git', '--git-dir', @repos, *args | |
end | |
end | |
class MakePostfixGitRepos | |
def initialize(tarballdir, gitrepos) | |
@tarballdir = tarballdir | |
@git = Git.new(gitrepos) | |
@versions = [] | |
end | |
def main | |
tmpf = Tempfile.new('make-postfix-git-repos') | |
@git.command 'log', '--all', '--date-order', '--format=format:%d', out: tmpf | |
tmpf.rewind | |
tmpf.each_line do |line| | |
line.slice(/\((.*)\)/, 1).split(/, /).each do |n| | |
if n =~ /\Atag: (.*)/ | |
@versions.push Version.new($1) | |
end | |
end | |
end | |
@versions = @versions.sort.reverse | |
files = Dir.glob("#{@tarballdir}/postfix-*.tar.gz").sort_by do |path| | |
[File.stat(path).mtime, Version.new(path)] | |
end | |
prev = @versions.first | |
files.each do |fname| | |
next if fname =~ /beta|RC|-\d\d\d\d\d\d\d\d/ | |
puts fname if $VERBOSE | |
ver = Version.new(fname) | |
next if @versions.include? ver | |
if prev && ver < prev && ver.str != '1.1.0' | |
p = @versions.find{|v| ver > v} | |
branch = p.branch_name | |
begin | |
@git.change_current_branch branch | |
rescue | |
@git.create_branch branch, p.str | |
@git.change_current_branch branch | |
end | |
commit fname | |
@git.change_current_branch 'master' | |
next | |
end | |
prev = ver | |
commit fname | |
@versions.unshift ver | |
end | |
end | |
def commit(fname) | |
ver = Version.new(fname) | |
date = File.stat(fname).mtime.strftime('%Y-%m-%dT00:00:00') | |
Dir.mktmpdir do |tmpdir| | |
system! 'tar', 'xpCf', tmpdir, fname | |
dir = Dir.glob("#{tmpdir}/*").first | |
return if dir =~ /snapshot/ | |
Dir.chdir dir do | |
@git.command '--work-tree=.', 'add', '--all', '.' | |
@git.command '--work-tree=.', 'commit', '-q', '--date', date, '-m', File.basename(fname, '.tar.gz') | |
@git.command 'tag', ver.str | |
end | |
end | |
end | |
end | |
MakePostfixGitRepos.new(*ARGV).main if __FILE__ == $0 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment