├── debian ├── docs ├── compat ├── dirs ├── .gitignore ├── changelog ├── copyright ├── control ├── preinst ├── postrm ├── postinst └── rules ├── gem ├── VERSION ├── doc │ └── .gitignore ├── .gitignore ├── README.rdoc ├── spec │ ├── spec.opts │ ├── spec_helper.rb │ └── commands │ │ └── gitian_spec.rb ├── lib │ ├── commands │ │ ├── abstract_gitian_command.rb │ │ └── gitian.rb │ └── rubygems_plugin.rb ├── script │ ├── gem-local │ └── gem-stats ├── gitian.gemspec └── Rakefile ├── .gitignore ├── doc ├── NOTES └── INSTALL ├── README.textile ├── Makefile ├── share └── completion │ ├── bash │ └── gitian │ └── zsh │ └── _gitian ├── lib ├── collect-gem-dependencies ├── gitian-package-build ├── gitian-package-new ├── tar-signer ├── gem-signer ├── gitian-release-build ├── gitian-release-upload └── gitian_util.py └── bin └── gitian /debian/docs: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /debian/compat: -------------------------------------------------------------------------------- 1 | 7 2 | -------------------------------------------------------------------------------- /gem/VERSION: -------------------------------------------------------------------------------- 1 | 0.0.3 2 | -------------------------------------------------------------------------------- /gem/doc/.gitignore: -------------------------------------------------------------------------------- 1 | spec 2 | -------------------------------------------------------------------------------- /gem/.gitignore: -------------------------------------------------------------------------------- 1 | pkg 2 | rdoc 3 | -------------------------------------------------------------------------------- /debian/dirs: -------------------------------------------------------------------------------- 1 | usr/bin 2 | usr/sbin 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *-stamp 2 | *.substvars 3 | *.log 4 | *.pyc 5 | -------------------------------------------------------------------------------- /doc/NOTES: -------------------------------------------------------------------------------- 1 | gem cert --build 2 | 3 | upgrade to rubygems 1.3.5 4 | -------------------------------------------------------------------------------- /gem/README.rdoc: -------------------------------------------------------------------------------- 1 | Gitian gem commands 2 | 3 | See https://gitian.org/howto 4 | -------------------------------------------------------------------------------- /debian/.gitignore: -------------------------------------------------------------------------------- 1 | nginz-admin 2 | *.log 3 | *.substvars 4 | files 5 | gitian 6 | -------------------------------------------------------------------------------- /README.textile: -------------------------------------------------------------------------------- 1 | h1. Gitian 2 | 3 | Read about the project goals at the "project home page":https://gitian.org/ . 4 | -------------------------------------------------------------------------------- /gem/spec/spec.opts: -------------------------------------------------------------------------------- 1 | --colour 2 | --format progress 3 | --loadby mtime 4 | --reverse 5 | --drb 6 | --format html:doc/spec/report.html 7 | 8 | -------------------------------------------------------------------------------- /gem/spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | $:.unshift File.expand_path(File.join(File.dirname(__FILE__), "../lib")) 2 | 3 | require 'rubygems' 4 | require 'rubygems_plugin' 5 | -------------------------------------------------------------------------------- /debian/changelog: -------------------------------------------------------------------------------- 1 | gitian (0.1-1) unstable; urgency=low 2 | 3 | * Initial release 4 | 5 | -- Miron Cuperman Sat, 26 Nov 2009 16:00:00 -0800 6 | -------------------------------------------------------------------------------- /debian/copyright: -------------------------------------------------------------------------------- 1 | This package is Copyright (C) 2009 Miron Cuperman 2 | and is licensed under the GPL version 3, see `/usr/share/common-licenses/GPL-3'. 3 | -------------------------------------------------------------------------------- /doc/INSTALL: -------------------------------------------------------------------------------- 1 | Debian dependencies: 2 | apt-get install python-git python-yaml 3 | 4 | If you have gems to distribute: 5 | rubygems 6 | gem install builder # used by 'gem generate_index' 7 | -------------------------------------------------------------------------------- /gem/lib/commands/abstract_gitian_command.rb: -------------------------------------------------------------------------------- 1 | require 'rubygems/local_remote_options' 2 | 3 | class Gem::AbstractGitianCommand < Gem::Command 4 | include Gem::LocalRemoteOptions 5 | 6 | URL = "https://gitian.org/rubygems/" 7 | end 8 | -------------------------------------------------------------------------------- /gem/lib/rubygems_plugin.rb: -------------------------------------------------------------------------------- 1 | $:.unshift File.dirname(__FILE__) # For use/testing when no gem is installed 2 | 3 | require 'rubygems/command_manager' 4 | require 'commands/abstract_gitian_command' 5 | 6 | %w[gitian].each do |command| 7 | require "commands/#{command}" 8 | Gem::CommandManager.instance.register_command command.to_sym 9 | end 10 | -------------------------------------------------------------------------------- /debian/control: -------------------------------------------------------------------------------- 1 | Source: gitian 2 | Section: misc 3 | Priority: extra 4 | Maintainer: Miron Cuperman 5 | Build-Depends: debhelper (>= 7) 6 | Standards-Version: 3.8.1 7 | Homepage: https://gitian.org/ 8 | 9 | Package: gitian 10 | Architecture: all 11 | Depends: ${misc:Depends}, git-core, python-yaml, python-git 12 | Description: Gitian distribution tools 13 | -------------------------------------------------------------------------------- /gem/script/gem-local: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | 3 | $:.unshift File.expand_path(File.join(File.dirname(__FILE__), "../lib")) 4 | 5 | require 'rubygems' 6 | require 'rubygems/gem_runner' 7 | require 'rubygems/exceptions' 8 | 9 | args = ARGV.clone 10 | 11 | begin 12 | Gem::GemRunner.new.run args 13 | rescue Gem::SystemExitException => e 14 | exit e.exit_code 15 | end 16 | 17 | 18 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # install into $DESTDIR 2 | install_dir=install -d -m 755 3 | install_file=install -m 644 4 | install_user_file=install -m 600 5 | install_script=install -m 755 6 | install_binary=install -m 755 -s 7 | varlib=$(DESTDIR)/var/lib/nginz 8 | user_skel=$(varlib)/skel 9 | 10 | all: 11 | echo done 12 | 13 | clean: 14 | echo cleaned 15 | 16 | install: 17 | $(install_dir) $(user_skel) 18 | $(install_file) nginz/.gemrc $(user_skel) 19 | $(install_dir) $(varlib)/vendor 20 | cp -a ../../../vendor/* $(varlib)/vendor 21 | chmod -R a+rX $(varlib)/vendor 22 | echo installed 23 | -------------------------------------------------------------------------------- /share/completion/bash/gitian: -------------------------------------------------------------------------------- 1 | # -*- shell-script -*- 2 | 3 | # experimental gitian bash completion 4 | 5 | _gitian_commands() 6 | { 7 | gitian shell-complete | sed -r 's/^(.*):.*/\1/' 8 | } 9 | 10 | _gitian_command_help() 11 | { 12 | gitian shell-complete $1 | sed -r 's/^\(-\)(-.*)\[.*/\1/' 13 | } 14 | 15 | _gitian() 16 | { 17 | cur=${COMP_WORDS[COMP_CWORD]} 18 | prev=${COMP_WORDS[COMP_CWORD-1]} 19 | if [ $COMP_CWORD -eq 1 ]; then 20 | COMPREPLY=( $( compgen -W "$(_gitian_commands)" $cur ) ) 21 | elif [ $COMP_CWORD -eq 2 ]; then 22 | COMPREPLY=( $( compgen -W "$(_gitian_command_help $prev)" $cur ) ) 23 | fi 24 | } 25 | 26 | complete -F _gitian -o default gitian 27 | 28 | -------------------------------------------------------------------------------- /lib/collect-gem-dependencies: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | 3 | dir = File.expand_path $*[0] 4 | 5 | $:.unshift dir + "/.gem/lib" 6 | require 'local_rubygems' 7 | require 'uri' 8 | 9 | index = Gem::SourceIndex.new 10 | index.update("file://#{dir}/rubygems", true) 11 | 12 | specs = {} 13 | deps = [] 14 | 15 | index.gems.values.each do |spec| 16 | specs[spec.name] = spec 17 | spec.dependencies.each do |dep| 18 | if dep.type == :runtime 19 | deps << dep 20 | end 21 | end 22 | end 23 | 24 | unsat = false 25 | deps.each do |dep| 26 | unless specs[dep.name] && dep =~ specs[dep.name] 27 | puts "Unsatisfied: #{dep.name} #{dep.version_requirements}" 28 | unsat = true 29 | else 30 | #puts "#{dep.inspect} satisfied by #{specs[dep.name].version}" 31 | end 32 | end 33 | 34 | exit(1) if unsat 35 | -------------------------------------------------------------------------------- /debian/preinst: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # preinst script for nginz-admin 3 | # 4 | # see: dh_installdeb(1) 5 | 6 | set -e 7 | 8 | # summary of how this script can be called: 9 | # * `install' 10 | # * `install' 11 | # * `upgrade' 12 | # * `abort-upgrade' 13 | # for details, see http://www.debian.org/doc/debian-policy/ or 14 | # the debian-policy package 15 | 16 | 17 | case "$1" in 18 | install|upgrade) 19 | ;; 20 | 21 | abort-upgrade) 22 | ;; 23 | 24 | *) 25 | echo "preinst called with unknown argument \`$1'" >&2 26 | exit 1 27 | ;; 28 | esac 29 | 30 | # dh_installdeb will replace this with shell code automatically 31 | # generated by other debhelper scripts. 32 | 33 | #DEBHELPER# 34 | 35 | exit 0 36 | -------------------------------------------------------------------------------- /share/completion/zsh/_gitian: -------------------------------------------------------------------------------- 1 | #compdef gitian 2 | 3 | # gitian is git-oriented software distribution system 4 | 5 | local curcontext="$curcontext" state line expl cmd args ret=1 6 | typeset -A opt_args 7 | 8 | _arguments -C \ 9 | '1: :->cmd' \ 10 | '*:: :->args' && ret=0 11 | 12 | if (( ! $+_gitian_cmds )); then 13 | typeset -gH _gitian_cmds 14 | _gitian_cmds=(${(f)"$(_call_program gitian gitian shell-complete)"}) 15 | fi 16 | 17 | if [[ $state != 'args' ]]; then 18 | _describe -t subcommand 'subcommand' _gitian_cmds 19 | return 0 20 | fi 21 | 22 | cmd="$words[1]" 23 | 24 | if [[ $cmd == 'help' ]]; then 25 | _describe -t subcommand 'subcommand' _gitian_cmds 26 | return 0 27 | fi 28 | 29 | curcontext="${curcontext%:*:*}:gitian-$cmd:" 30 | 31 | args=(${(f)"$(_call_program gitian gitian shell-complete $cmd)"}) 32 | _arguments -s "$args[@]" && ret=0 33 | return $ret 34 | -------------------------------------------------------------------------------- /debian/postrm: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # postrm script for nginz-admin 3 | # 4 | # see: dh_installdeb(1) 5 | 6 | set -e 7 | 8 | # summary of how this script can be called: 9 | # * `remove' 10 | # * `purge' 11 | # * `upgrade' 12 | # * `failed-upgrade' 13 | # * `abort-install' 14 | # * `abort-install' 15 | # * `abort-upgrade' 16 | # * `disappear' 17 | # 18 | # for details, see http://www.debian.org/doc/debian-policy/ or 19 | # the debian-policy package 20 | 21 | 22 | case "$1" in 23 | purge) 24 | ;; 25 | 26 | remove|upgrade|failed-upgrade|abort-install|abort-upgrade|disappear) 27 | ;; 28 | 29 | *) 30 | echo "postrm called with unknown argument \`$1'" >&2 31 | exit 1 32 | ;; 33 | esac 34 | 35 | # dh_installdeb will replace this with shell code automatically 36 | # generated by other debhelper scripts. 37 | 38 | #DEBHELPER# 39 | 40 | exit 0 41 | -------------------------------------------------------------------------------- /debian/postinst: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # postinst script for x1 3 | # 4 | # see: dh_installdeb(1) 5 | 6 | set -e 7 | 8 | # summary of how this script can be called: 9 | # * `configure' 10 | # * `abort-upgrade' 11 | # * `abort-remove' `in-favour' 12 | # 13 | # * `abort-remove' 14 | # * `abort-deconfigure' `in-favour' 15 | # `removing' 16 | # 17 | # for details, see http://www.debian.org/doc/debian-policy/ or 18 | # the debian-policy package 19 | 20 | 21 | case "$1" in 22 | configure) 23 | ;; 24 | 25 | abort-upgrade|abort-remove|abort-deconfigure) 26 | ;; 27 | 28 | *) 29 | echo "postinst called with unknown argument \`$1'" >&2 30 | exit 1 31 | ;; 32 | esac 33 | 34 | # dh_installdeb will replace this with shell code automatically 35 | # generated by other debhelper scripts. 36 | 37 | #DEBHELPER# 38 | 39 | exit 0 40 | -------------------------------------------------------------------------------- /bin/gitian: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | import subprocess 4 | import sys 5 | import os 6 | sys.path.append(os.path.join(os.path.dirname(sys.argv[0]), "../lib")) 7 | sys.path.append('/usr/lib/gitian') 8 | from gitian_util import * 9 | 10 | def check_command(command): 11 | if commands.get(command) is None: 12 | print>>sys.stderr, "usage: %s CMD\ntry: %s help"%(prog, prog) 13 | exit(1) 14 | return find_command(command) 15 | 16 | args = sys.argv[:] 17 | prog = args.pop(0) 18 | 19 | if len(args) < 1: 20 | print>>sys.stderr, "usage: %s CMD\n\ntry:\n %s help\nor:\n %s help CMD"%(prog, prog, prog) 21 | exit(1) 22 | 23 | commands = { 24 | "release-build": "Build all packages into the 'dist' directory", 25 | "package-build": "Build a single package into the 'dist' directory", 26 | "package-new": "Insert a new package into the distribution", 27 | "release-upload": "Upload a release to a web server", 28 | } 29 | if args[0] == "help": 30 | if len(args) == 1: 31 | for command in commands.keys(): 32 | print command, " - ", commands[command] 33 | else: 34 | command = args[1] 35 | command_path = find_command(command) 36 | ret = subprocess.call([command_path, "-h"]) 37 | elif args[0] == 'shell-complete': 38 | if len(args) == 1 or args[1] == "help": 39 | for command in commands.keys(): 40 | print "%s:%s"%(command, commands[command]) 41 | else: 42 | command = args[1] 43 | command_path = find_command(command) 44 | ret = subprocess.call([command_path, "--shell-complete"]) 45 | else: 46 | command = args.pop(0) 47 | command_path = find_command(command) 48 | args.insert(0, command_path) 49 | os.execv(command_path, args) 50 | 51 | -------------------------------------------------------------------------------- /gem/gitian.gemspec: -------------------------------------------------------------------------------- 1 | # Generated by jeweler 2 | # DO NOT EDIT THIS FILE DIRECTLY 3 | # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command 4 | # -*- encoding: utf-8 -*- 5 | 6 | Gem::Specification.new do |s| 7 | s.name = %q{gitian} 8 | s.version = "0.0.3" 9 | 10 | s.required_rubygems_version = Gem::Requirement.new(">= 1.3.5") if s.respond_to? :required_rubygems_version= 11 | s.authors = ["Miron Cuperman"] 12 | s.date = %q{2009-12-26} 13 | s.description = %q{Add the 'gitian' sub-commands to the gem command} 14 | s.email = %q{info.deb@nginz.org} 15 | s.files = [ 16 | "lib/commands/abstract_gitian_command.rb", 17 | "lib/commands/gitian.rb", 18 | "lib/rubygems_plugin.rb" 19 | ] 20 | s.homepage = %q{https://gitian.org/} 21 | s.post_install_message = %q{ 22 | ======================================================================== 23 | 24 | Thanks for installing Gitian! You can now run: 25 | 26 | gem gitian use Gitian.org or another distribution as your main gem source 27 | 28 | ======================================================================== 29 | 30 | } 31 | s.rdoc_options = ["--charset=UTF-8"] 32 | s.require_paths = ["lib"] 33 | s.rubyforge_project = %q{gitian-tools} 34 | s.rubygems_version = %q{1.3.5} 35 | s.summary = %q{Use a Gitian repository as the rubygems source} 36 | s.test_files = [ 37 | "spec/spec_helper.rb", 38 | "spec/commands/gitian_spec.rb" 39 | ] 40 | 41 | if s.respond_to? :specification_version then 42 | current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION 43 | s.specification_version = 3 44 | 45 | if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then 46 | s.add_development_dependency(%q, [">= 1.2.0"]) 47 | else 48 | s.add_dependency(%q, [">= 1.2.0"]) 49 | end 50 | else 51 | s.add_dependency(%q, [">= 1.2.0"]) 52 | end 53 | end 54 | 55 | -------------------------------------------------------------------------------- /gem/Rakefile: -------------------------------------------------------------------------------- 1 | require 'rubygems' 2 | require 'rake' 3 | require 'rake/rdoctask' 4 | 5 | begin 6 | require 'jeweler' 7 | Jeweler::Tasks.new do |gem| 8 | gem.rubyforge_project = "gitian-tools" 9 | gem.name = "gitian" 10 | gem.summary = "Use a Gitian repository as the rubygems source" 11 | gem.description = "Add the 'gitian' sub-commands to the gem command" 12 | gem.email = "info.deb@nginz.org" 13 | gem.homepage = "https://gitian.org/" 14 | gem.authors = ["Miron Cuperman"] 15 | gem.files = FileList["lib/rubygems_plugin.rb", "lib/commands/*"] 16 | gem.test_files = FileList["spec/*.rb", "spec/commands/*"] 17 | gem.executables = [] 18 | gem.add_development_dependency "rspec", ">= 1.2.0" 19 | gem.required_rubygems_version = Gem::Requirement.new(">= 1.3.5") if gem.respond_to? :required_rubygems_version= 20 | gem.post_install_message = < :build 50 | 51 | task :default => :spec 52 | 53 | task :spec => :check_dependencies 54 | 55 | desc "release with no version change" 56 | task :dist => [:clean, :release] 57 | 58 | namespace :dist do 59 | desc "release patch" 60 | task :patch => [:clean, "version:bump:patch", :release] 61 | desc "release with minor version bump" 62 | task :minor => [:clean, "version:bump:minor", :release] 63 | end 64 | 65 | Rake::RDocTask.new do |rd| 66 | version = File.exist?('VERSION') ? File.read('VERSION') : "" 67 | 68 | rd.main = "README.rdoc" 69 | rd.rdoc_dir = "rdoc" 70 | rd.title = "Gitian Gem #{version}" 71 | rd.rdoc_files.include("README.rdoc", "lib/**/*.rb") 72 | end 73 | 74 | task :clean do 75 | end 76 | -------------------------------------------------------------------------------- /lib/gitian-package-build: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | '''Gitian package builder''' 4 | 5 | import sys 6 | import os 7 | import git 8 | from gitian_util import * 9 | from optparse import OptionParser 10 | #from gettext import gettext as _ 11 | 12 | if __name__ == "__main__": 13 | parser = OptionParser() 14 | parser.prog = "gitian package-build" 15 | optparser_extend(parser) 16 | parser.add_option ("-c", "--clean", default=False, action="store_true", 17 | dest="clean", 18 | help="Start from a pristine checkout") 19 | parser.add_option ("-n", "--dry-run", default=False, action="store_true", 20 | dest="dryrun", 21 | help="Do not actually build - useful when cleaning") 22 | parser.add_option ("-b", "--blankslate", default=False, action="store_true", 23 | dest="blankslate", 24 | help="Clean out all installed gems before attempting build") 25 | parser.add_option ("-d", "--dest", 26 | dest="dest", 27 | help="Destination directory (default ROOT/dist)") 28 | parser.usage = """gitian package-new [-c COMMIT] REPOS-URL [NAME] 29 | or: 30 | gitian package-new GITHUB-COMMIT-URL [NAME] 31 | Creates a package within a Gitian repository 32 | """ 33 | (options, args) = parser.parse_args() 34 | if not args: 35 | parser.error("must supply package name") 36 | sys.exit(1) 37 | 38 | repos = repository_root() 39 | 40 | if options.dest: 41 | destination = os.path.abspath(options.dest) 42 | else: 43 | destination = os.path.join(repos, "dist") 44 | 45 | name = args[0] 46 | (package_dir, control, ptr) = open_package(name) 47 | 48 | if options.dryrun: 49 | sys.exit(0) 50 | 51 | if control['packager'] == 'rubygems': 52 | if options.blankslate: 53 | rubygems_dir = os.path.join(destination, '.gem') 54 | if os.access(rubygems_dir, os.F_OK): 55 | shutil.rmtree(rubygems_dir) 56 | ensure_rubygems_installed(destination) 57 | ensure_gem_installed('rake', destination) 58 | do_copy = True 59 | build_gem(package_dir, control, ptr, destination, do_copy, options.clean) 60 | if control['packager'] == 'tar': 61 | do_copy = True 62 | build_tar(package_dir, control, ptr, destination, do_copy, options.clean) 63 | else: 64 | print >> sys.stderr, "unknown packager %s" % (control['packager']) 65 | 66 | -------------------------------------------------------------------------------- /gem/spec/commands/gitian_spec.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') 2 | 3 | describe Gem::Commands::GitianCommand do 4 | before :each do 5 | @command = Gem::Commands::GitianCommand.new 6 | @command.stub!(:say) 7 | @url = "http://original/asdf" 8 | @new_url = "http://new/asdf/" 9 | @gitian_url = Gem::AbstractGitianCommand::URL 10 | @command.options[:release] = 'latest' 11 | end 12 | 13 | it "should set sources if url supplied" do 14 | @command.should_receive(:get_one_optional_argument).and_return(@new_url) 15 | Gem.configuration.should_receive(:[]).with("gitian_source").and_return(nil) 16 | Gem.configuration.should_receive(:[]=).with("gitian_source", @new_url + "latest/") 17 | Gem.configuration.should_receive(:[]).with("gem").and_return("--no-ri") 18 | Gem.configuration.should_receive(:[]=).with("gem", "--no-ri --trust-policy HighSecurity") 19 | Gem.configuration.should_receive(:write) 20 | Gem.should_receive(:sources).and_return([@url]) 21 | Gem.should_receive(:sources=).with([@new_url + "latest/", @url]) 22 | @command.execute 23 | end 24 | 25 | def normal_expects 26 | @command.should_receive(:get_one_optional_argument).and_return(nil) 27 | Gem.configuration.should_receive(:write) 28 | Gem.configuration.should_receive(:[]).with("gitian_source").and_return(nil) 29 | Gem.configuration.should_receive(:[]=).with("gitian_source", @gitian_url + "latest/") 30 | Gem.should_receive(:sources).and_return([@url]) 31 | Gem.should_receive(:sources=).with([@gitian_url + "latest/", @url]) 32 | end 33 | 34 | it "should set sources if url not supplied" do 35 | normal_expects 36 | Gem.configuration.should_receive(:[]).with("gem").and_return("--no-ri") 37 | Gem.configuration.should_receive(:[]=).with("gem", "--no-ri --trust-policy HighSecurity") 38 | @command.execute 39 | end 40 | 41 | it "should set gem command line if there wasn't one before" do 42 | normal_expects 43 | Gem.configuration.should_receive(:[]).with("gem").and_return(nil) 44 | Gem.configuration.should_receive(:[]=).with("gem", "--trust-policy HighSecurity") 45 | @command.execute 46 | end 47 | 48 | it "should override trust policy" do 49 | normal_expects 50 | Gem.configuration.should_receive(:[]).with("gem").and_return("--trust-policy NoSecurity") 51 | Gem.configuration.should_receive(:[]=).with("gem", "--trust-policy HighSecurity") 52 | @command.execute 53 | end 54 | 55 | it "should override trust policy anywhere on command line" do 56 | normal_expects 57 | Gem.configuration.should_receive(:[]).with("gem").and_return("--a --trust-policy=NoSecurity --b") 58 | Gem.configuration.should_receive(:[]=).with("gem", "--a --b --trust-policy HighSecurity") 59 | @command.execute 60 | end 61 | 62 | it "should allow insecurity" do 63 | normal_expects 64 | Gem.configuration.should_receive(:[]).with("gem").and_return(nil) 65 | Gem.configuration.should_receive(:[]=).with("gem", "--trust-policy MediumSecurity") 66 | @command.gitian(true, 'latest') 67 | end 68 | end 69 | 70 | -------------------------------------------------------------------------------- /debian/rules: -------------------------------------------------------------------------------- 1 | #!/usr/bin/make -f 2 | # -*- makefile -*- 3 | # Sample debian/rules that uses debhelper. 4 | # This file was originally written by Joey Hess and Craig Small. 5 | # As a special exception, when this file is copied by dh-make into a 6 | # dh-make output file, you may use that output file without restriction. 7 | # This special exception was added by Craig Small in version 0.37 of dh-make. 8 | 9 | # Uncomment this to turn on verbose mode. 10 | #export DH_VERBOSE=1 11 | 12 | install_dir=install -d -m 755 13 | install_file=install -m 644 14 | install_script=install -m 755 15 | install_binary=install -m 755 -s 16 | 17 | configure: configure-stamp 18 | configure-stamp: 19 | dh_testdir 20 | # Add here commands to configure the package. 21 | 22 | touch configure-stamp 23 | 24 | 25 | build: build-stamp 26 | 27 | build-stamp: configure-stamp 28 | dh_testdir 29 | 30 | # Add here commands to compile the package. 31 | $(MAKE) 32 | #docbook-to-man debian/nginz-admin.sgml > nginz-admin.1 33 | 34 | touch $@ 35 | 36 | clean: 37 | dh_testdir 38 | dh_testroot 39 | rm -f build-stamp configure-stamp 40 | 41 | # Add here commands to clean up after the build process. 42 | $(MAKE) clean 43 | 44 | dh_clean 45 | 46 | install: build 47 | dh_testdir 48 | dh_testroot 49 | dh_prep 50 | dh_installdirs 51 | 52 | 53 | # Build architecture-independent files here. 54 | binary-indep: install 55 | dh_testdir 56 | dh_testroot 57 | 58 | $(install_dir) $(CURDIR)/debian/gitian/usr/lib/gitian 59 | $(install_script) lib/gitian-package-build lib/gitian-package-new lib/gitian-release-upload lib/gitian-release-build $(CURDIR)/debian/gitian/usr/lib/gitian 60 | $(install_script) lib/gem-signer lib/collect-gem-dependencies $(CURDIR)/debian/gitian/usr/lib/gitian 61 | $(install_file) lib/*.py $(CURDIR)/debian/gitian/usr/lib/gitian 62 | 63 | $(install_dir) $(CURDIR)/debian/gitian/usr/bin 64 | $(install_file) bin/gitian $(CURDIR)/debian/gitian/usr/bin 65 | 66 | $(install_dir) $(CURDIR)/debian/gitian/usr/share/zsh/functions/Completion/Unix/ 67 | $(install_file) share/completion/zsh/_gitian $(CURDIR)/debian/gitian/usr/share/zsh/functions/Completion/Unix/ 68 | 69 | $(install_dir) $(CURDIR)/debian/gitian/etc/bash_completion.d 70 | $(install_file) share/completion/bash/gitian $(CURDIR)/debian/gitian/etc/bash_completion.d 71 | 72 | dh_installchangelogs 73 | dh_installdocs 74 | dh_installexamples 75 | # dh_install 76 | # dh_installmenu 77 | # dh_installdebconf 78 | # dh_installlogrotate 79 | # dh_installemacsen 80 | # dh_installpam 81 | # dh_installmime 82 | # dh_installinit 83 | # dh_installcron 84 | # dh_installinfo 85 | # dh_installwm 86 | # dh_installudev 87 | # dh_lintian 88 | # dh_undocumented 89 | dh_installman 90 | dh_link 91 | dh_compress 92 | dh_fixperms 93 | # dh_perl 94 | # dh_python 95 | dh_installdeb 96 | dh_gencontrol 97 | dh_md5sums 98 | dh_builddeb 99 | 100 | # Build architecture-dependent files here. 101 | binary-arch: install 102 | 103 | binary: binary-indep binary-arch 104 | .PHONY: build clean binary-indep binary-arch binary install configure 105 | -------------------------------------------------------------------------------- /lib/gitian-package-new: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | '''Gitian package creator''' 4 | 5 | import os 6 | import sys 7 | import re 8 | from gitian_util import * 9 | from optparse import OptionParser 10 | from urlparse import urlparse 11 | 12 | if __name__ == "__main__": 13 | parser = OptionParser() 14 | parser.prog = "gitian package-build" 15 | parser.add_option ("-c", "--commit", 16 | dest="commit", 17 | help="Git commit (if a github URL is not specified)") 18 | parser.usage = """gitian package-new -c COMMIT REPOS-URL [NAME] 19 | or: 20 | gitian package-new GITHUB-COMMIT-URL [NAME] 21 | Creates a package within a Gitian repository 22 | """ 23 | optparser_extend(parser) 24 | (options, args) = parser.parse_args() 25 | 26 | 27 | if len(args) < 1 or len(args) > 2: 28 | parser.print_usage() 29 | exit(1) 30 | 31 | url = args[0] 32 | 33 | name = None 34 | if len(args) == 2: 35 | name = args[1] 36 | 37 | p_url = urlparse(url) 38 | 39 | if p_url.netloc == "github.com" and p_url.scheme == 'http': 40 | match = re.match('\A/([^/]+)/([^/]+)/commit/([^/]+)\Z', p_url.path) 41 | if match is None: 42 | print >> sys.stderr, "could not parse github commit url" 43 | exit(1) 44 | url = "git://github.com/%s/%s.git"%(match.group(1), match.group(2)) 45 | commit = match.group(3) 46 | else: 47 | commit = options.commit 48 | 49 | if not commit: 50 | parser.error("must specify a commit") 51 | exit(1) 52 | 53 | if name is None: 54 | match = re.match('.*/([^/.]+?)(.git)?\Z', url) 55 | if match is None: 56 | print >> sys.stderr, "could not parse git url" 57 | exit(1) 58 | 59 | name = match.group(1) 60 | 61 | repos = repository_root() 62 | path = os.path.join(repos, "packages", name) 63 | 64 | created = False 65 | 66 | control_path = os.path.join(path, "control") 67 | if not os.access(control_path, os.F_OK): 68 | created = True 69 | os.makedirs(path) 70 | control_f = open(control_path, "w") 71 | control = { 72 | 'name': name, 73 | 'packager': 'rubygems', 74 | 'packager_options': 75 | { 76 | 'build_cmd': "$RAKE_CMD gem" 77 | } 78 | } 79 | yaml.dump(control, control_f, 80 | default_flow_style=False, explicit_start=True) 81 | control_f.close() 82 | 83 | ptr_f = open(os.path.join(path, name + ".vcptr"), "w") 84 | ptr = { 'url': url, 'commit': commit } 85 | yaml.dump(ptr, ptr_f, 86 | default_flow_style=False, explicit_start=True) 87 | ptr_f.close() 88 | 89 | (package_dir, control, ptr) = open_package(name) 90 | os.chdir(package_dir) 91 | 92 | prepare_build_package(ptr, True) 93 | 94 | # If there's a gemspec, use that instead 95 | if created and os.access(os.path.join('build', name + ".gemspec"), os.F_OK): 96 | control_f = open(control_path, "w") 97 | control['packager_options']['build_cmd'] = "$GEM_CMD build %s.gemspec"%(name) 98 | yaml.dump(control, control_f, 99 | default_flow_style=False, explicit_start=True) 100 | control_f.close() 101 | 102 | if created: 103 | print "created %s" %(name) 104 | else: 105 | print "updated %s" %(name) 106 | -------------------------------------------------------------------------------- /lib/tar-signer: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | 3 | require 'rubygems' 4 | require 'rubygems/package' 5 | require 'digest/sha2' 6 | require 'time' 7 | require 'ostruct' 8 | require 'optparse' 9 | 10 | # Ensure that hashes (if any) output in a deterministic way. 11 | # This assumes that keys are all comparable and of same type - 12 | # i.e. will fail with symbols. 13 | # Gem specs usually don't have any hashes, so this is just in case. 14 | 15 | TAR_ENTRY_MODE = 0600 16 | TAR_DIR_ENTRY_MODE = 0700 17 | 18 | # Allow access to the gzip IO 19 | class Gem::Package::TarWriter 20 | attr_reader :io 21 | end 22 | 23 | require 'optparse' 24 | 25 | options = OpenStruct.new 26 | options.digest_file = nil 27 | options.check_digest = true 28 | options.quiet = false 29 | options.date = "1970-01-01 00:00:00 +00:00" 30 | 31 | opts = OptionParser.new do |opts| 32 | opts.banner = "Usage: tar-signer [options] IN_TAR OUT_TAR" 33 | 34 | opts.on("-d", "--date DATE", "Reference date, default to 1970-01-01 UTC") do |date| 35 | options.date = date 36 | end 37 | 38 | opts.on("-q", "--quiet", "Be less verbose about digest mismatch") do |flag| 39 | options.quiet = flag 40 | end 41 | 42 | opts.on("-n", "--[no-]digest-check", "Check that digest did not change (default on)") do |flag| 43 | options.check_digest = flag 44 | end 45 | 46 | opts.on("-o", "--digest-output FILE", "put gem digest in FILE") do |out| 47 | options.digest_file = out 48 | end 49 | 50 | opts.on_tail("-h", "--help", "Show this message") do 51 | puts opts 52 | exit 53 | end 54 | end 55 | 56 | opts.parse! 57 | 58 | file = $*[0] 59 | outfile = $*[1] 60 | 61 | unless file && outfile 62 | $stderr.puts opts 63 | exit(1) 64 | end 65 | 66 | digest = Digest::SHA2.new(256) 67 | 68 | File.open(outfile, "wb") do |out_f| 69 | File.open(file, "rb") do |in_f| 70 | Gem::Package::TarReader.new(in_f) do |reader| 71 | Gem::Package::TarWriter.new(out_f) do |writer| 72 | entries = {} 73 | 74 | # FIXME should not read everything into memory 75 | reader.each do |entry| 76 | content = entry.read 77 | 78 | entries[entry.full_name] = [ entry, content ] 79 | end 80 | 81 | # Sort entries to make data part deterministic 82 | entries.keys.sort.each do |key| 83 | entry = entries[key][0] 84 | content = entries[key][1] 85 | if entry.directory? 86 | writer.mkdir entry.full_name, TAR_DIR_ENTRY_MODE 87 | else 88 | writer.add_file_simple entry.full_name, TAR_ENTRY_MODE, entry.header.size do |tar_io| 89 | digest.update(entry.header.size.to_s) 90 | digest.update("\001") 91 | digest.update(entry.full_name) 92 | digest.update("\000") 93 | content = "" if content.nil? 94 | digest.update(content) 95 | tar_io.write content 96 | end 97 | end 98 | end 99 | end 100 | end 101 | end 102 | end 103 | 104 | digest_out = digest.hexdigest 105 | 106 | if options.digest_file 107 | if options.check_digest && File.exists?(options.digest_file) 108 | File::open(options.digest_file, "r") do |io| 109 | digest_in = io.read.chomp 110 | if digest_in != digest_out 111 | $stderr.puts("digest mismatch:\n" + 112 | " #{digest_out} !=\n #{digest_in}") unless options.quiet 113 | exit(1) 114 | end 115 | end 116 | end 117 | File::open(options.digest_file, "w") do |io| 118 | io.puts(digest.hexdigest) 119 | end 120 | else 121 | puts digest.hexdigest 122 | end 123 | -------------------------------------------------------------------------------- /gem/lib/commands/gitian.rb: -------------------------------------------------------------------------------- 1 | require 'net/http' 2 | require 'net/https' 3 | require 'digest/sha1' 4 | require 'rubygems/security' 5 | 6 | class Gem::Commands::GitianCommand < Gem::AbstractGitianCommand 7 | def description 8 | 'Use a Gitian distribution as the primary gem source and enable gem security' 9 | end 10 | 11 | def arguments 12 | "[URL] URL of Gitian distribution, (see -g for default)" 13 | end 14 | 15 | def usage 16 | "#{program_name} [URL]" 17 | end 18 | 19 | def initialize 20 | super 'gitian', description 21 | 22 | defaults.merge!( 23 | :undo => false, 24 | :release => nil, 25 | :gitian => false, 26 | :re_get_cert => false, 27 | :status => false 28 | ) 29 | 30 | add_option('-r', '--release REL', 'Specify a release (default is "latest")') do |value, options| 31 | options[:release] = value 32 | end 33 | 34 | add_option('-g', '--use-gitian', "Switch to #{URL}") do |value, options| 35 | options[:gitian] = true 36 | end 37 | 38 | add_option('', '--re-get-cert', 'Get the signing certificate again') do |value, options| 39 | options[:re_get_cert] = true 40 | end 41 | 42 | add_option('-u', '--undo', 'Disable gitian (so that you can install from an insecure repository)') do |value, options| 43 | options[:undo] = true 44 | end 45 | add_option('-s', '--status', 'Show status') do |value, options| 46 | options[:status] = true 47 | end 48 | end 49 | 50 | def execute 51 | if options[:undo] 52 | undo() 53 | elsif options[:status] 54 | else 55 | gitian(options[:gitian], options[:release]) 56 | end 57 | show_status 58 | end 59 | 60 | def undo 61 | unless Gem.configuration["saved_srcs"] 62 | puts "There is no saved configuration" 63 | return 64 | end 65 | 66 | gem_opts = Gem.configuration["gem"] || "" 67 | gem_opts.gsub!(/\s*--trust-policy[ =]\S+/, "") 68 | Gem.configuration["gem"] = gem_opts.strip 69 | Gem.sources = Gem.configuration["saved_srcs"] 70 | Gem.configuration["saved_srcs"] = nil 71 | 72 | Gem.configuration.write 73 | end 74 | 75 | def gitian(use_gitian, release) 76 | gem_opts = Gem.configuration["gem"] || "" 77 | gem_opts.gsub!(/\s*--trust-policy[ =]\S+/, "") 78 | policy = "HighSecurity" 79 | gem_opts = gem_opts + " --trust-policy #{policy}" 80 | Gem.configuration["gem"] = gem_opts.strip 81 | oldurl = Gem.configuration["gitian_source"] 82 | 83 | url = get_one_optional_argument 84 | if url 85 | release ||= 'latest' 86 | else 87 | if use_gitian || oldurl.nil? 88 | url = URL 89 | release ||= 'latest' 90 | else 91 | # if using old URL, strip last component only if release given 92 | url = oldurl 93 | url = URI.parse(url).merge("..").to_s if release 94 | end 95 | end 96 | 97 | url += "/" if url[-1,1] != "/" 98 | url = url + release + "/" if release 99 | 100 | sources = Gem.sources 101 | sources.reject! { |s| s == url || s == oldurl } 102 | if !sources.empty? 103 | Gem.configuration["saved_srcs"] = sources 104 | end 105 | sources = [ url ] 106 | Gem.sources = sources 107 | Gem.configuration["gitian_source"] = url 108 | 109 | uri = URI.parse(url) 110 | if uri.relative? 111 | $stderr.puts "URL must be absolute - i.e. start with http://, https://, file:///" 112 | $stderr.puts "" 113 | show_help() 114 | exit(1) 115 | end 116 | 117 | get_cert(uri, options[:re_get_cert]) 118 | 119 | Gem.configuration.write 120 | 121 | say "High security policy enabled. You will get an 'unsigned gem' error if you try to install a gem from a normal, non-signing gem repository. Use 'gem gitian --undo' if you want to install an unsigned gem." 122 | end 123 | 124 | def show_status 125 | puts "Sources in ~/.gemrc:" 126 | Gem.sources.each do |source| 127 | puts "- #{source}" 128 | end 129 | puts "Gem defaults: #{Gem.configuration["gem"]}" if Gem.configuration["gem"] && Gem.configuration["gem"] != "" 130 | end 131 | 132 | def get_cert(uri, do_force) 133 | http = Net::HTTP.new(uri.host, uri.port) 134 | if uri.scheme == 'https' 135 | http.use_ssl = true 136 | end 137 | http.start do 138 | cert_uri = uri.merge("../gem-public_cert.pem") 139 | http.request_get(cert_uri.path) do |res| 140 | case res 141 | when Net::HTTPSuccess 142 | # OK 143 | else 144 | $stderr.puts "Could not get certificate at #{cert_uri}" 145 | res.error! 146 | end 147 | cert = OpenSSL::X509::Certificate.new(res.body) 148 | path = Gem::Security::Policy.trusted_cert_path(cert) 149 | return if (!do_force && File.exists?(path)) 150 | Gem::Security.add_trusted_cert(cert) 151 | digest = Digest::SHA1.hexdigest(cert.to_der) 152 | digest = digest.upcase.gsub(/../, '\0:').chop 153 | subject = cert.subject.to_s 154 | subject.sub!("/CN=", '') 155 | subject.sub!("/DC=", '@') 156 | subject.gsub!("/DC=", '.') 157 | puts "Please verify fingerprint for <#{subject}> is\n #{digest}" 158 | end 159 | end 160 | end 161 | 162 | end 163 | -------------------------------------------------------------------------------- /lib/gem-signer: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | 3 | require 'rubygems' 4 | require 'rubygems/package' 5 | require 'digest/sha2' 6 | require 'time' 7 | require 'ostruct' 8 | require 'optparse' 9 | 10 | # Ensure that hashes (if any) output in a deterministic way. 11 | # This assumes that keys are all comparable and of same type - 12 | # i.e. will fail with symbols. 13 | # Gem specs usually don't have any hashes, so this is just in case. 14 | 15 | TAR_ENTRY_MODE = 0640 16 | 17 | class Hash 18 | def to_yaml( opts = {} ) 19 | YAML::quick_emit( self, opts ) do |out| 20 | out.map( taguri, to_yaml_style ) do |map| 21 | keys.sort.each do |k| 22 | map.add( k, self[k] ) 23 | end 24 | end 25 | end 26 | end 27 | end 28 | 29 | # Allow access to the gzip IO 30 | class Gem::Package::TarWriter 31 | attr_reader :io 32 | end 33 | 34 | require 'optparse' 35 | 36 | options = OpenStruct.new 37 | options.key = "cert/gem-private_key.pem" 38 | options.cert = "cert/gem-public_cert.pem" 39 | options.digest_file = nil 40 | options.check_digest = true 41 | options.quiet = false 42 | options.date = "1970-01-01 00:00:00 +00:00" 43 | 44 | opts = OptionParser.new do |opts| 45 | opts.banner = "Usage: gem-signer [options] IN_GEM OUT_GEM" 46 | 47 | opts.on("-d", "--date DATE", "Reference date, default to 1970-01-01 UTC") do |date| 48 | options.date = date 49 | end 50 | 51 | opts.on("-q", "--quiet", "Be less verbose about digest mismatch") do |flag| 52 | options.quiet = flag 53 | end 54 | 55 | opts.on("-n", "--[no-]digest-check", "Check that digest did not change (default on)") do |flag| 56 | options.check_digest = flag 57 | end 58 | 59 | opts.on("-o", "--digest-output FILE", "put gem digest in FILE") do |out| 60 | options.digest_file = out 61 | end 62 | 63 | opts.on("-c", "--cert-file FILE[,FILE]*", "public cert chain in FILE(s) (default to #{options.cert})") do |file| 64 | options.cert = file 65 | end 66 | 67 | opts.on("-k", "--key-file FILE", "private key in FILE (default to #{options.key})") do |file| 68 | options.key = file 69 | end 70 | 71 | opts.on_tail("-h", "--help", "Show this message") do 72 | puts opts 73 | exit 74 | end 75 | end 76 | 77 | opts.parse! 78 | 79 | file = $*[0] 80 | outfile = $*[1] 81 | 82 | unless file && outfile 83 | $stderr.puts opts 84 | exit(1) 85 | end 86 | 87 | signer = Gem::Security::Signer.new options.key, options.cert.split(',') 88 | digest = Digest::SHA2.new(256) 89 | 90 | File.open(outfile, "wb") do |out_f| 91 | File.open(file, "rb") do |in_f| 92 | Gem::Package.open(out_f, "w", signer) do |out_pkg| 93 | Gem::Package.open(in_f, "r") do |in_pkg| 94 | # Set the time to a deterministic value 95 | spec = in_pkg.metadata 96 | spec.date = Time.parse(options.date) 97 | out_pkg.io.mtime = spec.date.to_i 98 | spec.cert_chain = signer.cert_chain.map { |cert| cert.to_s } 99 | 100 | # Make specs deterministic by sorting anything that might be 101 | # reordered. Specs should be identical other than the cert_chain. 102 | spec.files = spec.files.sort 103 | spec.test_files = spec.test_files.sort 104 | spec.extra_rdoc_files = spec.extra_rdoc_files.sort 105 | spec.executables = spec.executables.sort 106 | out_pkg.metadata = spec.to_yaml 107 | spec.cert_chain = [] 108 | digest.update(spec.to_yaml) 109 | 110 | entries = {} 111 | 112 | # FIXME should not read everything into memory 113 | in_pkg.each do |entry| 114 | content = entry.read 115 | 116 | # Skip any gemspecs in the data part, they are not needed 117 | # and their date can change 118 | next if entry.full_name =~ /.gemspec$/ 119 | 120 | entries[entry.full_name] = [ entry, content ] 121 | end 122 | 123 | # Sort entries to make data part deterministic 124 | entries.keys.sort.each do |key| 125 | entry = entries[key][0] 126 | content = entries[key][1] 127 | out_pkg.add_file_simple entry.full_name, TAR_ENTRY_MODE, entry.header.size do |tar_io| 128 | digest.update(entry.header.size.to_s) 129 | digest.update("\001") 130 | digest.update(entry.full_name) 131 | digest.update("\000") 132 | unless content.nil? 133 | digest.update(content) 134 | tar_io.write content 135 | end 136 | end 137 | end 138 | end 139 | end 140 | end 141 | end 142 | 143 | digest_out = digest.hexdigest 144 | 145 | if options.digest_file 146 | if options.check_digest && File.exists?(options.digest_file) 147 | File::open(options.digest_file, "r") do |io| 148 | digest_in = io.read.chomp 149 | if digest_in != digest_out 150 | $stderr.puts("digest mismatch:\n" + 151 | " #{digest_out} !=\n #{digest_in}") unless options.quiet 152 | exit(1) 153 | end 154 | end 155 | end 156 | File::open(options.digest_file, "w") do |io| 157 | io.puts(digest.hexdigest) 158 | end 159 | else 160 | puts digest.hexdigest 161 | end 162 | -------------------------------------------------------------------------------- /lib/gitian-release-build: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | '''Gitian release builder''' 4 | 5 | import sys 6 | import os 7 | import yaml 8 | import fnmatch 9 | import glob 10 | import shutil 11 | from gitian_util import * 12 | from optparse import OptionParser 13 | #from gettext import gettext as _ 14 | 15 | if __name__ == "__main__": 16 | parser = OptionParser() 17 | parser.prog = "gitian release-build" 18 | optparser_extend(parser) 19 | parser.add_option ("-b", "--blankslate", default=False, action="store_true", 20 | dest="blankslate", 21 | help="Start building from a blank slate") 22 | parser.add_option ("-c", "--clean", default=False, action="store_true", 23 | dest="clean", 24 | help="Clean each package checkout before building") 25 | parser.add_option ("-n", "--dry-run", default=False, action="store_true", 26 | dest="dryrun", 27 | help="Do not actually build anything, but still generate release index") 28 | 29 | (options, args) = parser.parse_args() 30 | 31 | repos = repository_root() 32 | os.chdir(repos) 33 | 34 | destination = os.path.join(repos, "dist") 35 | 36 | if not os.access("gitian-repos", os.F_OK): 37 | print >> sys.stderr, "must be run within the gitian repository" 38 | exit(1) 39 | 40 | repos_f = open("gitian-repos", "r") 41 | gitian_repos = yaml.load(repos_f) 42 | repos_f.close() 43 | 44 | reference_date = gitian_repos['date'] 45 | reference_date_str = reference_date.strftime("%Y-%m-%d %H:%M:%S +00:00") 46 | 47 | if options.blankslate and os.access('dist', os.F_OK): 48 | shutil.rmtree('dist') 49 | 50 | if options.blankslate and os.access('stage', os.F_OK): 51 | shutil.rmtree('stage') 52 | 53 | if not os.access("logs", os.F_OK): 54 | os.makedirs("logs") 55 | 56 | print "Building packages" 57 | 58 | if options.dryrun: 59 | print "[DRYRUN]" 60 | 61 | failures = 0 62 | for dsc in glob.glob('packages/*/control'): 63 | package = os.path.basename(os.path.dirname(dsc)) 64 | print " - " + package 65 | if options.dryrun: 66 | continue 67 | 68 | blankslate_option = '' 69 | if options.blankslate: 70 | blankslate_option = ' --blankslate' 71 | 72 | clean_option = '' 73 | if options.clean: 74 | clean_option = ' --clean' 75 | res = os.system(find_command("package-build") + "%s%s --dest %s %s > logs/build-%s.log 2>&1"% 76 | (blankslate_option, 77 | clean_option, 78 | os.path.abspath('stage'), 79 | package, 80 | package)) 81 | if res != 0: 82 | print >> sys.stderr, "FAILED - see logs/build-%s.log"% (package) 83 | failures += 1 84 | 85 | digest_dir = os.path.join("digests", "default") 86 | stage_gems_dir = os.path.join("stage", "rubygems", "gems") 87 | stage_tars_dir = os.path.join("stage", "rubygems", "tars") 88 | dist_gems_dir = os.path.join(destination, "rubygems", "gems") 89 | dist_tars_dir = os.path.join(destination, "rubygems", "tars") 90 | 91 | if not os.access(digest_dir, os.F_OK): 92 | os.makedirs(digest_dir) 93 | 94 | if not os.access(dist_gems_dir, os.F_OK): 95 | os.makedirs(dist_gems_dir) 96 | 97 | if not os.access(dist_tars_dir, os.F_OK): 98 | os.makedirs(dist_tars_dir) 99 | 100 | ensure_rubygems_installed(destination) 101 | ensure_gem_installed('rake', destination) 102 | ensure_gem_installed('builder', destination) 103 | 104 | if failures: 105 | print >> sys.stderr, "failed to build %s packages"%(failures) 106 | sys.exit(1) 107 | 108 | os.chdir(repos) 109 | 110 | print "Signing gems" 111 | for gem_file in glob.glob(os.path.join(stage_gems_dir, '*.gem')): 112 | new_file = os.path.join(dist_gems_dir, os.path.basename(gem_file)) 113 | digest_file = os.path.join(digest_dir, os.path.basename(gem_file)+".digest") 114 | res = os.system(find_command("gem-signer") + ' --date "%s" --digest-output %s --quiet "%s" "%s"'%(reference_date_str, digest_file, gem_file, new_file)) 115 | if res != 0: 116 | print >> sys.stderr, "FAILED %s"%(gem_file) 117 | 118 | print "Hashing tars" 119 | for tar_file in glob.glob(os.path.join(stage_tars_dir, '*.tar')): 120 | new_file = os.path.join(dist_tars_dir, os.path.basename(tar_file)) 121 | digest_file = os.path.join(digest_dir, os.path.basename(tar_file)+".digest") 122 | res = os.system(find_command("tar-signer") + ' --date "%s" --digest-output %s --quiet "%s" "%s"'%(reference_date_str, digest_file, tar_file, new_file)) 123 | if res != 0: 124 | print >> sys.stderr, "FAILED %s"%(tar_file) 125 | 126 | print "Indexing gems" 127 | res = os.system("gem generate_index --directory dist/rubygems > logs/generate_index.log") 128 | if res != 0: 129 | print >> sys.stderr, "gem generate_index failed - see logs/generate_index.log" 130 | sys.exit(1) 131 | 132 | res = os.system(find_command("collect-gem-dependencies") + " %s"%('dist')) 133 | if res != 0: 134 | sys.exit(1) 135 | -------------------------------------------------------------------------------- /gem/script/gem-stats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | 3 | require 'rubygems' 4 | require 'zlib' 5 | require 'json' 6 | require 'yaml' 7 | require 'set' 8 | require 'optparse' 9 | require 'ostruct' 10 | 11 | options = OpenStruct.new 12 | options.cutoff = 100 13 | options.yaml = false 14 | 15 | opts = OptionParser.new do |opts| 16 | opts.banner = <<-EOF 17 | Usage: gem-stats DIR 18 | Expects a directory with -.gemspec.rz and gemcutter .json files 19 | Displays a table with: 20 | * Score rank 21 | * Score 22 | * Score from dependencies 23 | * Downloads 24 | * Number of gems needed to achieve closure for gems at this and higher rank 25 | * Name 26 | * Any messages regarding missing dependencies 27 | 28 | EOF 29 | opts.on("-c", "--cutoff CUTOFF", "Score cutoff") do |cutoff| 30 | options.cutoff = cutoff 31 | end 32 | opts.on("-y", "--yaml", "Output YAML to stats.yaml instead of text") do |yaml| 33 | options.yaml = yaml 34 | end 35 | opts.on_tail("-h", "--help", "Show this message") do 36 | puts opts 37 | exit 38 | end 39 | end 40 | 41 | opts.parse! 42 | 43 | unless $*[0] 44 | $stderr.puts opts 45 | exit(1) 46 | end 47 | 48 | 49 | def load_entries(dir) 50 | entries = [] 51 | problems = 0 52 | Dir.new(dir).each do |file| 53 | if file =~ /\.json$/ 54 | begin 55 | entry = JSON.load(File.read("#{dir}/#{file}")) 56 | rescue JSON::ParserError 57 | puts "could not parse #{file}" 58 | end 59 | rzfile = "#{entry['name']}-#{entry['version']}.gemspec.rz" 60 | begin 61 | spec = Marshal.load(Zlib::Inflate.inflate(File.read("#{dir}/#{rzfile}"))) 62 | entry[:deps] = spec.dependencies 63 | rescue 64 | #puts "could not open #{rzfile}" 65 | problems += 1 66 | next 67 | end 68 | entries << entry 69 | end 70 | end 71 | puts "could not open #{problems} files" 72 | 73 | entries 74 | end 75 | 76 | if File.exist?('dump.yaml') 77 | puts "loading from dump" 78 | entries = [] 79 | File.open("dump.yaml", "r") do |f| 80 | YAML.each_document(f) do |entry| 81 | entries << entry 82 | end 83 | end 84 | else 85 | puts "loading from source" 86 | entries = load_entries($*[0]) 87 | File.open("dump.yaml", "w") do |f| 88 | entries.each do |entry| 89 | YAML.dump(entry, f) 90 | end 91 | end 92 | end 93 | 94 | all_entries = {} 95 | 96 | # Reverse dependency map 97 | dev_deps = {} 98 | run_deps = {} 99 | 100 | entries.each do |entry| 101 | name = entry['name'] 102 | all_entries[name] = entry 103 | entry[:score] = entry['downloads'] 104 | entry[:depscore] = 0 105 | entry[:missing] = nil 106 | entry[:deps].each do |dep| 107 | dev_deps[dep.name] ||= Set.new 108 | run_deps[dep.name] ||= Set.new 109 | dev_deps[dep.name] << entry if dep.type == :development 110 | run_deps[dep.name] << entry if dep.type == :runtime 111 | end 112 | end 113 | 114 | entries.each do |entry| 115 | name = entry['name'] 116 | if dev_deps[name] 117 | dev_deps[name].each do |dep| 118 | entry[:score] += dep['downloads'] / 10 119 | entry[:depscore] += dep['downloads'] / 10 120 | end 121 | run_deps[name].each do |dep| 122 | entry[:score] += dep['downloads'] / 10 123 | entry[:depscore] += dep['downloads'] 124 | end 125 | end 126 | end 127 | 128 | # Used to close the set of gems needed to satisfy all 129 | # dependencies of entries in set. 130 | class Closure 131 | def initialize(all) 132 | @set = Hash.new 133 | @all = all 134 | end 135 | 136 | def <<(entry) 137 | added_deps = Set.new 138 | 139 | return added_deps if @set.has_key?(entry['name']) 140 | new_deps = Hash.new 141 | new_deps[entry['name']] = entry 142 | 143 | while (!new_deps.empty?) 144 | deps = new_deps 145 | new_deps = Hash.new 146 | deps.each_value do |dep| 147 | dep_name = dep['name'] 148 | unless @set.has_key?(dep_name) || new_deps.has_key?(dep_name) 149 | @set[dep_name] = dep 150 | added_deps << dep 151 | dep[:deps].each do |subdep| 152 | subdep_entry = @all[subdep.name] 153 | if subdep_entry 154 | new_deps[subdep.name] = subdep_entry 155 | else 156 | if subdep.type == :runtime 157 | entry[:missing] ||= 'MISSING: ' 158 | entry[:missing] += subdep.name + "? " 159 | end 160 | end 161 | end 162 | end 163 | end 164 | end 165 | return added_deps 166 | end 167 | 168 | def size() 169 | @set.size() 170 | end 171 | 172 | def set() 173 | @set 174 | end 175 | end 176 | 177 | closure = Closure.new(all_entries) 178 | 179 | entries = entries.sort_by { |e| -e[:score] } 180 | 181 | if options.yaml 182 | File.open("stats.yaml", "w") do |outf| 183 | entries.each do |entry| 184 | break if entry[:score] < options.cutoff 185 | adds = (closure << entry) 186 | entry[:closure_adds] = adds.map { |d| d['name'] } 187 | YAML.dump(entry, outf) 188 | end 189 | end 190 | else 191 | puts sprintf("%4s %9s %9s %9s %9s name", "rank", "score", "depscore", "downloads", "closure", "name") 192 | 193 | index = 0 194 | entries.each do |e| 195 | index += 1 196 | break if e[:score] < options.cutoff 197 | closure << e 198 | puts sprintf("%4d %9d %9d %9d %9d %s %s", index, e[:score].to_s, e[:depscore], e['downloads'], closure.size(), e['name'], e[:missing]) 199 | end 200 | end 201 | -------------------------------------------------------------------------------- /lib/gitian-release-upload: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | '''Gitian release upload''' 4 | 5 | import sys 6 | import os 7 | import yaml 8 | import commands 9 | import re 10 | import tempfile 11 | import shutil 12 | import glob 13 | from string import Template 14 | from gitian_util import * 15 | from optparse import OptionParser 16 | #from gettext import gettext as _ 17 | 18 | def process_static_files(release, rc): 19 | static_files_dir = os.path.join("static-files", "rubygems") 20 | for static_file in glob.glob(os.path.join(static_files_dir, "*.tpl")): 21 | result_base = os.path.basename(static_file)[0:-4] 22 | new_file = os.path.join("dist", "rubygems", result_base) 23 | in_f = open(static_file, "r") 24 | out_f = open(new_file, "w") 25 | content = in_f.read() 26 | content = Template(content).safe_substitute(PUBLIC_URL = rc["public_url"], RELEASE = release) 27 | out_f.write(content) 28 | in_f.close() 29 | out_f.close() 30 | 31 | def push_repo(rsync_flags, url, release_url): 32 | res = os.system("rsync -a%s --chmod=go=rX --delete-after dist/rubygems/ %s"%(rsync_flags, release_url)) 33 | if res != 0: 34 | print >>sys.stderr, "rsync failed, abort" 35 | sys.exit(1) 36 | res = os.system("rsync -a%s --chmod=go=rX --copy-links cert/gem-public_cert.pem %s"%(rsync_flags, url)) 37 | if res != 0: 38 | print >>sys.stderr, "rsync failed, abort" 39 | sys.exit(1) 40 | 41 | if __name__ == "__main__": 42 | parser = OptionParser() 43 | parser.prog = "gitian release-upload" 44 | optparser_extend(parser) 45 | parser.add_option ("-u", "--url", 46 | dest="url", 47 | help="Target rsync URL, or previously used URL if omitted") 48 | parser.add_option ("-p", "--public_url", 49 | dest="public_url", 50 | help="HTTP/HTTPS URL as seen by public, or previously used URL if omitted") 51 | parser.add_option ("-n", "--dry-run", default=False, action="store_true", 52 | dest="dryrun", 53 | help="Do a dry-run rsync") 54 | parser.add_option ("-v", "--verbose", default=False, action="store_true", 55 | dest="verbose", 56 | help="Make rsync verbose") 57 | parser.add_option ("-r", "--release", 58 | dest="release", 59 | help="Target release, defaults to 'dev' unless at a signed git tag") 60 | parser.usage = """%prog [options] CMD 61 | where CMD is: 62 | help - show more help 63 | push - release to distribution 64 | delete - delete a release 65 | list - list releases 66 | release - push, then set the 'latest' release symlink""" 67 | 68 | (options, args) = parser.parse_args() 69 | 70 | if len(args) != 1: 71 | parser.error("must supply command") 72 | 73 | cmd = args[0] 74 | 75 | if cmd == "help": 76 | parser.print_help() 77 | sys.exit(1) 78 | 79 | repos = repository_root() 80 | os.chdir(repos) 81 | 82 | if not os.access("dist/rubygems/gems", os.F_OK): 83 | print >> sys.stderr, "dist/rubygems/gems directory does not exist" 84 | sys.exit(1) 85 | 86 | try: 87 | rc_f = open(".gitianrc") 88 | rc = yaml.load(rc_f) 89 | rc_f.close() 90 | except Exception, e: 91 | rc = {} 92 | 93 | url = options.url 94 | 95 | if url is None: 96 | url = rc.get("push_url") 97 | if url is None: 98 | parser.error("no rsync URL saved in .gitianrc, please supply with --url") 99 | sys.exit(1) 100 | else: 101 | rc["push_url"] = url 102 | rc_f = open(".gitianrc", "w") 103 | yaml.dump(rc, rc_f) 104 | rc_f.close() 105 | 106 | public_url = options.public_url 107 | 108 | if public_url is None: 109 | public_url = rc.get("public_url") 110 | if public_url is None: 111 | print>>sys.stderr, "no public url saved in .gitianrc, please supply with --public-url" 112 | sys.exit(1) 113 | else: 114 | rc["public_url"] = url 115 | rc_f = open(".gitianrc", "w") 116 | yaml.dump(rc, rc_f) 117 | rc_f.close() 118 | 119 | 120 | release = options.release 121 | if release is None: 122 | # Figure out if at a signed git tag 123 | (status, output) = commands.getstatusoutput("git describe") 124 | if status != 0: 125 | print output 126 | print >> sys.stderr, "'git describe' failed, do you have a signed tag" 127 | sys.exit(1) 128 | match = re.match('\Av(\d+.\d+.\d+)\Z', output) 129 | if match is None: 130 | release = 'dev' 131 | else: 132 | release = match.group(1) 133 | print "Release: %s"%(release) 134 | 135 | release_url = url + "/" + release 136 | rsync_flags = '' 137 | if options.verbose: rsync_flags += 'v' 138 | if options.dryrun: rsync_flags += 'n' 139 | 140 | if cmd == "push": 141 | process_static_files(release, rc) 142 | push_repo(rsync_flags, url, release_url) 143 | elif cmd == "delete": 144 | if release == 'dev': 145 | print >> sys.stderr, "cannot delete since release is 'dev'" 146 | sys.exit(1) 147 | t_dir = tempfile.mkdtemp('gitian') 148 | res = 1 149 | try: 150 | res = os.system("rsync -a%s --delete %s/ %s"%(rsync_flags, t_dir, release_url)) 151 | finally: 152 | shutil.rmtree(t_dir) 153 | if res != 0: 154 | print >>sys.stderr, "rsync failed, abort" 155 | sys.exit(1) 156 | print "deleted contents of %s"%(release_url) 157 | 158 | elif cmd == "release": 159 | if release == 'dev': 160 | print >> sys.stderr, "cannot release when current release is 'dev'. Must be at a git signed release tag." 161 | sys.exit(1) 162 | process_static_files(release, rc) 163 | push_repo(rsync_flags, url, release_url) 164 | t_dir = tempfile.mkdtemp('gitian') 165 | res = 1 166 | try: 167 | latest = os.path.join(t_dir, "latest") 168 | os.symlink(release, latest) 169 | res = os.system("rsync -a%s %s %s"%(rsync_flags, latest, url)) 170 | finally: 171 | shutil.rmtree(t_dir) 172 | if res != 0: 173 | print >>sys.stderr, "rsync failed, abort" 174 | sys.exit(1) 175 | 176 | elif cmd == "list": 177 | os.system("rsync --dirs %s/"%(url)) 178 | elif cmd == "help": 179 | parser.help() 180 | else: 181 | parser.error("unknown command") 182 | -------------------------------------------------------------------------------- /lib/gitian_util.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import yaml 3 | import os 4 | import shutil 5 | import fnmatch 6 | from optparse import SUPPRESS_HELP 7 | 8 | def prepare_build_package(ptr, do_clean = False): 9 | if not os.access("build", os.F_OK): 10 | os.makedirs("build") 11 | res = os.system("cd build && git init") 12 | if res != 0: 13 | print >> sys.stderr, "git init failed" 14 | sys.exit(1) 15 | 16 | do_clean = True 17 | 18 | if do_clean: 19 | os.system("cd build && git remote | grep --quiet '^origin$' && git remote rm origin") 20 | res = os.system("cd build && git remote add origin '%s'" % (ptr['url'])) 21 | if res != 0: 22 | print >> sys.stderr, "git remote add failed" 23 | sys.exit(1) 24 | 25 | res = os.system("cd build && git fetch --quiet origin") 26 | if res != 0: 27 | print >> sys.stderr, "git fetch failed" 28 | sys.exit(1) 29 | 30 | res = os.system("cd build && git checkout -f '%s'" % (ptr['commit'])) 31 | if res != 0: 32 | print >> sys.stderr, "git checkout failed" 33 | sys.exit(1) 34 | 35 | res = os.system("cd build && git clean -d -f -x") 36 | if res != 0: 37 | print >> sys.stderr, "git clean failed" 38 | sys.exit(1) 39 | 40 | def open_package(name): 41 | repos = repository_root() 42 | 43 | package_dir = os.path.join(repos, "packages", name) 44 | 45 | try: 46 | control_f = open(os.path.join(package_dir, "control")) 47 | except IOError, e: 48 | print >> sys.stderr, "package does not exist - %s"%(name) 49 | sys.exit(1) 50 | 51 | control = yaml.load(control_f) 52 | control_f.close() 53 | 54 | name = control['name'] 55 | ptr_f = open(os.path.join(package_dir, name + '.vcptr')) 56 | 57 | if ptr_f is None: 58 | print >> sys.stderr, "could not open version control pointer file" 59 | sys.exit(1) 60 | 61 | ptr = yaml.load(ptr_f) 62 | ptr_f.close() 63 | 64 | return (package_dir, control, ptr) 65 | 66 | 67 | def repository_root(): 68 | dir = os.getcwd() 69 | parent = os.path.dirname(dir) 70 | while (parent != dir): 71 | if os.access(os.path.join(dir, "gitian-repos"), os.F_OK): 72 | return dir 73 | 74 | dir = parent 75 | parent = os.path.dirname(dir) 76 | 77 | print >> sys.stderr, "must be run within the gitian repository" 78 | exit(1) 79 | 80 | def shell_complete(option, opt, value, parser): 81 | for option in parser.option_list: 82 | for flag in str(option).split('/'): 83 | if option.help != SUPPRESS_HELP: 84 | print "(-)%s[%s]"%(flag, option.help) 85 | exit(0) 86 | 87 | def optparser_extend(parser): 88 | parser.add_option ("", "--shell-complete", action="callback", 89 | callback=shell_complete, 90 | help=SUPPRESS_HELP 91 | ) 92 | 93 | def find_command(command): 94 | progdir = os.path.dirname(sys.argv[0]) 95 | 96 | for dir in [os.path.join(progdir, "../lib"), "/usr/lib/gitian"]: 97 | if os.access(os.path.join(dir, command), os.F_OK): 98 | found_dir = dir 99 | return os.path.join(dir, command) 100 | 101 | command = "gitian-" + command 102 | 103 | for dir in [os.path.join(progdir, "../lib"), "/usr/lib/gitian"]: 104 | if os.access(os.path.join(dir, command), os.F_OK): 105 | found_dir = dir 106 | return os.path.join(dir, command) 107 | 108 | print>>sys.stderr, "installation problem - could not find subcommand %s"%(command) 109 | exit(1) 110 | 111 | def build_tar(package_dir, control, ptr, destination, do_copy=False, do_clean=False): 112 | name = control['name'] 113 | 114 | os.chdir(package_dir) 115 | 116 | prepare_build_package(ptr, do_clean) 117 | 118 | packager_options = control.get('packager_options', {}) or {} 119 | 120 | build_cmd = packager_options.get('build_cmd', 'rake -t -rlocal_rubygems gem') 121 | os.chdir(package_dir) 122 | 123 | print "Building package %s (copy=%s)" % (name, do_copy) 124 | res = os.system("cd build && %s" % (build_cmd)) 125 | if res != 0: 126 | print >> sys.stderr, "build failed" 127 | sys.exit(1) 128 | if do_copy: 129 | copy_tars_to_dist("build", destination) 130 | 131 | def build_gem(package_dir, control, ptr, destination, do_copy=False, do_clean=False): 132 | name = control['name'] 133 | 134 | os.chdir(package_dir) 135 | 136 | prepare_build_package(ptr, do_clean) 137 | 138 | packager_options = control.get('packager_options', {}) or {} 139 | 140 | build_cmd = packager_options.get('build_cmd', 'rake -t -rlocal_rubygems gem') 141 | packages = control.get('packages') 142 | 143 | depends = control.get('build_depends', []) or [] 144 | for depend in depends: 145 | ensure_gem_installed(depend, destination) 146 | 147 | os.chdir(package_dir) 148 | 149 | if packages: 150 | for package in packages: 151 | print "Building package %s (copy=%s)" % (package, do_copy) 152 | # default to package name 153 | dir = control['directories'].get(package, package) 154 | subdir = os.path.join("build", dir) 155 | res = os.system("cd %s && %s" % (subdir, build_cmd)) 156 | if res != 0: 157 | print >> sys.stderr, "build in build/%s failed" % (dir) 158 | sys.exit(1) 159 | if do_copy: 160 | copy_gems_to_dist(subdir, destination) 161 | 162 | else: 163 | print "Building package %s (copy=%s)" % (name, do_copy) 164 | res = os.system("cd build && %s" % (build_cmd)) 165 | if res != 0: 166 | print >> sys.stderr, "build failed" 167 | sys.exit(1) 168 | if do_copy: 169 | copy_gems_to_dist("build", destination) 170 | 171 | def copy_gems_to_dist(subdir, destination): 172 | print "installing to %s"%(destination) 173 | gems_destination = os.path.join(destination, "rubygems/gems") 174 | found = False 175 | for dirpath, dirs, files in os.walk(subdir): 176 | for file in fnmatch.filter(files, '*-*.*.gem'): 177 | if not os.access(gems_destination, os.F_OK): 178 | os.makedirs(gems_destination) 179 | shutil.copy(os.path.join(dirpath, file), gems_destination) 180 | found = True 181 | if not found: 182 | print >> sys.stderr, "no gem found" 183 | sys.exit(1) 184 | 185 | def copy_tars_to_dist(subdir, destination): 186 | print "installing to %s"%(destination) 187 | tars_destination = os.path.join(destination, "rubygems/tars") 188 | found = False 189 | for dirpath, dirs, files in os.walk(subdir): 190 | for file in fnmatch.filter(files, '*-*.*.tar'): 191 | if not os.access(tars_destination, os.F_OK): 192 | os.makedirs(tars_destination) 193 | shutil.copy(os.path.join(dirpath, file), tars_destination) 194 | found = True 195 | if not found: 196 | print >> sys.stderr, "no tar found" 197 | sys.exit(1) 198 | 199 | GEM_CHECK_COMMAND = "ruby -rlocal_rubygems -e 'exit(Gem.source_index.find_name(\"%s\").length==0?1:0)'" 200 | 201 | def ensure_gem_installed(gem, dest): 202 | components = gem.split("/") 203 | if len(components) == 1: 204 | package = gem 205 | else: 206 | (package, gem) = components 207 | 208 | res = os.system(GEM_CHECK_COMMAND%(gem)) 209 | if res != 0: 210 | (package_dir, control, ptr) = open_package(package) 211 | build_gem(package_dir, control, ptr, dest) 212 | install_built_gems(dest, gem) 213 | 214 | res = os.system(GEM_CHECK_COMMAND%(gem)) 215 | if res != 0: 216 | print >>sys.stderr, "failed to install gem %s" % (gem) 217 | 218 | def install_built_gems(dest, gem = None): 219 | gemrc = os.path.join(dest, "gemrc") 220 | for dirpath, dirs, files in os.walk('build'): 221 | if gem is None: 222 | pattern = '*.gem' 223 | else: 224 | pattern = "%s-*.gem"%(gem) 225 | 226 | for file in fnmatch.filter(files, pattern): 227 | cmd = "gem --config-file '%s' install --no-ri --no-rdoc --ignore-dependencies %s"%( 228 | gemrc, os.path.join(dirpath, file)) 229 | res = os.system(cmd) 230 | if res != 0: 231 | print >>sys.stderr, "failed to install gem with: %s" % (cmd) 232 | 233 | def ensure_rubygems_installed(dest): 234 | gemhome = os.path.join(dest, ".gem") 235 | if not os.access(os.path.join(gemhome, "bin", "gem1.8"), os.F_OK): 236 | (package_dir, control, ptr) = open_package("rubygems") 237 | os.chdir(package_dir) 238 | 239 | prepare_build_package(ptr) 240 | res = os.system("cd build && ruby setup.rb --no-ri --no-rdoc --prefix=%s > /dev/null" % (gemhome)) 241 | if res != 0 or not os.access(os.path.join(gemhome, "bin", "gem1.8"), os.F_OK): 242 | print >>sys.stderr, "build failed in %s" % (dir) 243 | sys.exit(1) 244 | local_rubygems_rb = os.path.join(gemhome, "lib", "local_rubygems.rb") 245 | if not os.access(local_rubygems_rb, os.F_OK): 246 | rb_f = open(local_rubygems_rb, "w") 247 | print >>rb_f, """require "rubygems" 248 | Gem.configuration = Gem::ConfigFile.new [ "--config-file=/dev/null" ] 249 | Gem.sources = ["/dev/null"] 250 | Gem.use_paths(ENV['GEM_HOME'], [ENV['GEM_HOME']]) 251 | """ 252 | rb_f.close() 253 | gemrc = os.path.join(dest, "gemrc") 254 | if not os.access(gemrc, os.F_OK): 255 | gemrc_f = open(gemrc, "w") 256 | print >>gemrc_f, """--- 257 | :gemhome: %s 258 | :gempath: 259 | - %s 260 | :sources: 261 | - bogus: 262 | """%(gemhome, gemhome) 263 | gemrc_f.close() 264 | os.environ['GEM_HOME'] = gemhome 265 | os.environ['PATH'] = os.path.join(gemhome, "bin") + ":" + os.environ['PATH'] 266 | os.environ['RUBYLIB'] = os.path.join(gemhome, "lib") 267 | os.environ['RAKE_CMD'] = "rake -rlocal_rubygems" 268 | os.environ['RAKE_ARGS'] = "-rlocal_rubygems" 269 | os.environ['GEM_CMD'] = "gem1.8 --config-file=%s"%(gemrc) 270 | os.environ['GEM_ARGS'] = "--config-file=%s"%(gemrc) 271 | 272 | --------------------------------------------------------------------------------