--- rant-0.5.8.orig/lib/rant/rantlib.rb +++ rant-0.5.8/lib/rant/rantlib.rb @@ -89,8 +89,8 @@ def ask_yes_no text $stderr.print msg_prefix + text + " [y|n] " case $stdin.readline - when /y|yes/i: true - when /n|no/i: false + when /y|yes/i; true + when /n|no/i; false else $stderr.puts(' ' * msg_prefix.length + "Please answer with `yes' or `no'") @@ -427,9 +427,9 @@ ### support for subdirectories ################################### def expand_path(subdir, path) case path - when nil: subdir.dup - when "": subdir.dup - when /^@/: path.sub(/^@/, '') + when nil; subdir.dup + when ""; subdir.dup + when /^@/; path.sub(/^@/, '') else path = path.sub(/^\\(?=@)/, '') if subdir.empty? @@ -1010,7 +1010,7 @@ return s if s } [] - when Rant::Node: [s] + when Rant::Node; [s] else # assuming list of tasks s end @@ -1027,7 +1027,7 @@ return s if s } [] - when Rant::Node: [s] + when Rant::Node; [s] else s end @@ -1173,7 +1173,7 @@ cmd_opts.quiet = true cmd_opts.each { |opt, value| case opt - when "--verbose": @opts[:verbose] += 1 + when "--verbose"; @opts[:verbose] += 1 when "--version" puts "rant #{Rant::VERSION}" raise Rant::RantDoneException --- rant-0.5.8.orig/lib/rant/import.rb +++ rant-0.5.8/lib/rant/import.rb @@ -218,20 +218,20 @@ cmd_opts.quiet = true cmd_opts.each { |opt, value| case opt - when "--version": + when "--version" puts "rant-import #{Rant::VERSION}" done - when "-v": + when "-v" warn_msg "Option `-v' is deprecated and won't be in", "release 0.6.0. Use `-V' or `--version' instead!." puts "rant-import #{Rant::VERSION}" done - when "--help": help - when "--quiet": @quiet = true - when "--force": @force = true - when "--with-comments": @skip_comments = false - when "--reduce-whitespace": @reduce_whitespace = true - when "--zip": @zip = true + when "--help"; help + when "--quiet"; @quiet = true + when "--force"; @force = true + when "--with-comments"; @skip_comments = false + when "--reduce-whitespace"; @reduce_whitespace = true + when "--zip"; @zip = true when "--imports" @imports.concat(value.split(/\s*,\s*/)) when "--plugins" @@ -287,7 +287,7 @@ begin rantlib = File.read rantlib_f rescue - abort("When trying to read `#{rantlib_f}': #$!", + abort("When trying to read `#{rantlib_f}'; #$!", "This file should contains the core of rant, so import is impossible.", "Please check your rant installation!") end --- rant-0.5.8.orig/lib/rant/node.rb +++ rant-0.5.8/lib/rant/node.rb @@ -83,8 +83,8 @@ def reference_name sd = rac.current_subdir case sd - when "": full_name - when project_subdir: name + when ""; full_name + when project_subdir; name else "@#{full_name}".sub(/^@#{Regexp.escape sd}\//, '') end end --- rant-0.5.8.orig/lib/rant/rantvar.rb +++ rant-0.5.8/lib/rant/rantvar.rb @@ -265,8 +265,8 @@ # A +vid+ has to be a String to be valid. def valid_vid(obj) case obj - when String: obj - when Symbol: obj.to_s + when String; obj + when Symbol; obj.to_s else if obj.respond_to? :to_str obj.to_str --- rant-0.5.8.orig/lib/rant/coregen.rb +++ rant-0.5.8/lib/rant/coregen.rb @@ -154,8 +154,8 @@ } } end - when Proc: src_arg - when nil: lambda { |name| [] } + when Proc; src_arg + when nil; lambda { |name| [] } else rac.abort_at(ch, "rule source has to be a " + "String, Array or Proc") @@ -200,8 +200,8 @@ def create_nodes(rel_project_dir, target, deps) @rant.goto_project_dir rel_project_dir case nodes = @block[target, deps] - when Array: nodes - when Node: [nodes] + when Array; nodes + when Node; [nodes] else @rant.abort_at(@ch, "Block has to " + "return Node or array of Nodes.") @@ -226,11 +226,11 @@ class Action def self.rant_gen(rac, ch, args, &block) case args.size - when 0: + when 0 unless (rac[:tasks] || rac[:stop_after_load]) yield end - when 1: + when 1 rx = args.first unless rx.kind_of? Regexp rac.abort_at(ch, "Action: argument has " + --- rant-0.5.8.orig/lib/rant/import/command.rb +++ rant-0.5.8/lib/rant/import/command.rb @@ -112,9 +112,9 @@ private def val_for_interp_var(var) case var - when "name": self.name - when "prerequisites": prerequisites.map { |n| rac.resolve_root_ref(n) } - when "source": rac.resolve_root_ref(source) + when "name"; self.name + when "prerequisites"; prerequisites.map { |n| rac.resolve_root_ref(n) } + when "source"; rac.resolve_root_ref(source) else cx = rac.cx val = cx.var._get(var) || ( @@ -142,9 +142,9 @@ end def val_for_interp_sym(sym) case sym - when ">": name - when "<": prerequisites.map { |n| rac.resolve_root_ref(n) } - when "-": rac.resolve_root_ref(source) + when ">"; name + when "<"; prerequisites.map { |n| rac.resolve_root_ref(n) } + when "-"; rac.resolve_root_ref(source) end end end --- rant-0.5.8.orig/lib/rant/import/rubypackage.rb +++ rant-0.5.8/lib/rant/import/rubypackage.rb @@ -9,8 +9,8 @@ self.new(:app => app, :__caller__ => ch, &block) elsif args.size == 1 pkg_name = case args.first - when String: args.first - when Symbol: args.first.to_s + when String; args.first + when Symbol; args.first.to_s else app.abort("RubyPackage takes only one additional " + "argument, which should be a string or symbol.") --- rant-0.5.8.orig/lib/rant/import/var/booleans.rb +++ rant-0.5.8/lib/rant/import/var/booleans.rb @@ -21,14 +21,14 @@ false elsif val.respond_to? :to_str case val.to_str - when /^\s*true\s*$/i: true - when /^\s*false\s*$/i: false - when /^\s*y(es)?\s*$/i: true - when /^\s*n(o)?\s*$/: false - when /^\s*on\s*$/i: true - when /^\s*off\s*$/i: false - when /^\s*1\s*$/: true - when /^\s*0\s*$/: false + when /^\s*true\s*$/i; true + when /^\s*false\s*$/i; false + when /^\s*y(es)?\s*$/i; true + when /^\s*n(o)?\s*$/; false + when /^\s*on\s*$/i; true + when /^\s*off\s*$/i; false + when /^\s*1\s*$/; true + when /^\s*0\s*$/; false else raise ConstraintError.new(self, val) end --- rant-0.5.8.orig/debian/install +++ rant-0.5.8/debian/install @@ -0,0 +1,7 @@ +bin/ usr +lib/rant usr/lib/ruby/1.8 +lib/rant usr/lib/ruby/1.9.1 +doc/* usr/share/doc/rant +misc usr/share/doc/rant +debian/doc/examples usr/share/doc/rant +debian/bash/rant etc/bash_completion.d --- rant-0.5.8.orig/debian/changelog +++ rant-0.5.8/debian/changelog @@ -0,0 +1,103 @@ +rant (0.5.8-8) unstable; urgency=medium + + * move ruby 1.9 branch to 1.9.1 from 1.9.0 (Closes: #569856) + + * debian/control update standards version to 3.8.4 + + * debian/control build-depends requires debhelper, include ${misc:Depends}, + fix lintian warning + + * debian/rules simplified + + -- Ralph Amissah Fri, 19 Feb 2010 15:11:00 -0500 + +rant (0.5.8-7) unstable; urgency=low + + * rant build package example adjusted + + -- Ralph Amissah Fri, 03 Oct 2008 19:15:08 -0400 + +rant (0.5.8-6) unstable; urgency=medium + + * package updated to follow the last version of Debian Policy + (Standards-Version 3.8.0 instead of 3.7.3) + + -- Ralph Amissah Mon, 23 Jun 2008 00:05:40 -0400 + +rant (0.5.8-5) unstable; urgency=medium + + * fix to path for ruby1.9 library should (Closes: #484623) + + * updated to debhelper >= 7 control and compat + + * control description touched + + -- Ralph Amissah Wed, 18 Jun 2008 13:10:32 -0400 + +rant (0.5.8-4) unstable; urgency=low + + * rant build package example updated + + * debian/rules dh_link softlinks added for build package example Rantfile + and Rakefile to common example rbuild in + /usr/share/doc/rant/examples/debian_package/ + + -- Ralph Amissah Wed, 12 Dec 2007 16:40:53 +0000 + +rant (0.5.8-3) unstable; urgency=low + + * debian build version updated + + * debian maintainer upload permissions + + * debian clean rules + + * debian control homepage tag + + -- Ralph Amissah Sun, 09 Dec 2007 15:18:26 +0000 + +rant (0.5.8-2) unstable; urgency=low + + * replaced : with ; after conditions (if|unless|elsif|when), as required by + ruby 1.9 + + * provided debian build package example Rantfile (for ruby programs, uses + git-buildpackage) [should be easily extensible] + + * updated to debhelper >= 5 control and compat + + * moved mapping of doc to /usr/share/doc/rant (from /usr/share/doc/rant/doc) + + * added rant ruby1.9 library [requires testing] + + * minor edit of man pages (make reference to rant-import in rant man page) + + -- Ralph Amissah Thu, 28 Jun 2007 00:22:02 +0100 + +rant (0.5.8-1) unstable; urgency=medium + + * New upstream release + + * dpatch removed, not required, generic ruby path corrected upstream + + -- Ralph Amissah Fri, 1 Dec 2006 09:29:50 +0000 + +rant (0.5.6-3) unstable; urgency=low + + * updated bash completion, (Russel Winder) + + -- Ralph Amissah Sun, 1 Oct 2006 14:18:59 +0100 + +rant (0.5.6-2) unstable; urgency=low + + * added bash completion contributed by Russel Winder, LGPL + + * added lintian override for two empty documentation files + + -- Ralph Amissah Tue, 15 Aug 2006 02:47:37 +0100 + +rant (0.5.6-1) unstable; urgency=low + + * Rant package ITP done (Closes: #369366) + + -- Ralph Amissah Fri, 28 Jul 2006 00:38:23 +0100 --- rant-0.5.8.orig/debian/manpages +++ rant-0.5.8/debian/manpages @@ -0,0 +1,2 @@ +debian/man/man1/rant.1 +debian/man/man1/rant-import.1 --- rant-0.5.8.orig/debian/compat +++ rant-0.5.8/debian/compat @@ -0,0 +1 @@ +7 --- rant-0.5.8.orig/debian/control +++ rant-0.5.8/debian/control @@ -0,0 +1,18 @@ +Source: rant +Section: devel +Priority: optional +Maintainer: Ralph Amissah +XS-Dm-Upload-Allowed: yes +Build-Depends: debhelper (>= 7) +Standards-Version: 3.8.4 +Homepage: http://rant.rubyforge.org/ + +Package: rant +Architecture: all +Depends: ${misc:Depends}, ruby (>= 1.8.2) +Description: Flexible, Ruby based make + Similar to make, the rant commandline tool reads a file called Rantfile, which + contains task definitions. Unlike make, however, an Rantfile is just a valid + script written in the Ruby programming language. Since Ruby comes with many + useful libraries and is portable across many different operating systems, it + is easy to write portable Rantfiles. --- rant-0.5.8.orig/debian/rant.lintian-overrides +++ rant-0.5.8/debian/rant.lintian-overrides @@ -0,0 +1 @@ +rant: zero-byte-file-in-doc-directory --- rant-0.5.8.orig/debian/README.Debian +++ rant-0.5.8/debian/README.Debian @@ -0,0 +1,18 @@ +rant for Debian +--------------- + +bash completion contributed by Russel Winder +program source: + + + + -- Ralph Amissah , Thu, 14 Aug 2006 00:55:17 +0100 + +author Stefan Lang, program source can be found at: + + + +* test directory removed from source package + + -- Ralph Amissah , Thu, 15 Jun 2006 00:55:17 +0100 + --- rant-0.5.8.orig/debian/rules +++ rant-0.5.8/debian/rules @@ -0,0 +1,34 @@ +#!/usr/bin/make -f +#export DH_VERBOSE=1 + +clean: + dh_testdir + dh_testroot + dh_clean + +build: + +install: + +binary: binary-indep + +binary-arch: + +binary-indep: + dh_testdir + dh_testroot + dh_installdocs README + dh_installchangelogs + dh_installman + dh_install + dh_lintian + dh_link usr/share/doc/rant/examples/debian_package/rbuild usr/share/doc/rant/examples/debian_package/Rantfile + dh_link usr/share/doc/rant/examples/debian_package/rbuild usr/share/doc/rant/examples/debian_package/Rakefile + dh_compress -X.rb -X.yml -XRantfile -XRakefile -Xrbuild -Xdeb_pkg_r + dh_fixperms + dh_installdeb + dh_gencontrol + dh_md5sums + dh_builddeb + +.PHONY: clean build install binary binary-arch binary-indep --- rant-0.5.8.orig/debian/copyright +++ rant-0.5.8/debian/copyright @@ -0,0 +1,172 @@ +Package Rant debianized by Ralph Amissah on +Wed, 28 July 2006 22:53:49 +0100. + +It was downloaded from + +Copyright Holder: Stefan Lang + apart from setup.rb, rubyzip and minitar which are the works of other authors + +License: LGPL - GNU Lesser General Public License + + Copyright (C) 2005,2006 Stefan Lang + + This package is free software; you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License as published by the Free + Software Foundation; either version 2.1 of the License, or (at your option) + any later version. + + This package is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + details. + + You should have received a copy of the GNU Lesser General Public License + along with this package; if not, write to the Free Software Foundation, Inc., + 51 Franklin St, Fifth Floor, Boston, MA 0211 0-1301, USA. + +On Debian GNU/Linux systems, the complete text of the GNU Lesser General Public +License can be found in '/usr/share/common-licenses/LGPL'. + +License (setup.rb) + + Copyright (c) 2000-2004 Minero Aoki + + GNU LGPL, Lesser General Public License version 2.1 (same license as main + package "Rant", as above). + + Hompepage: + + +License (rubyzip,ioextras,stdrubyext) + + Copyright (c) 2000,20002,2003,2004 Thomas Sondergaard + (with extra-field support contributed by Tatsuki Sugiura) + + Free software under the Ruby's License (appended below) + + Homepage and project site: + + + +License (minitar) + + Copyright (c) 2004 Mauricio Julio Fernandez Pradier and Austin Ziegler + + GPL version 2 (or later) or Ruby's licence (appended below) + + program is based on and incorporates parts of RPA::Package from rpa-base + (lib/rpa/package.rb and lib/rpa/util.rb) by Mauricio and has been adapted to + be more generic by Austin. 'minitar' contains an adaptation of + Ruby/ProgressBar by Satoru Takabayashi + + Project site: + + +License (ruby/progressbar) + + Copyright (c) Satoru Takabayashi 2001-2004 + + Ruby's License (appended below) + + Homepage: + + +License (bash completion for Rant) + + Copyright (c) 2006 Russel Winder + + LGPL - GNU Lesser General Public License (same as Rant) + + Source: + + + +APPENDIX - GPL 2 (GNU General Public License) + +GPL 2 (GNU General Public License) summary: + + This program is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free Software + Foundation; either version 2 of the License, or (at your option) any later + version. + + This program is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + details. + + You should have received a copy of the GNU General Public License along with + this package; if not, write to the Free Software Foundation, Inc., 51 + Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + + If you have Internet connection, the latest version of the GPL should be + available from these locations: + + + + + On Debian systems, the complete text of the GNU General Public License can be + found in `/usr/share/common-licenses/GPL'. + + The Free Software Foundation: + + +APPENDIX - Ruby License + +Ruby License + + Ruby is copyrighted free software by Yukihiro Matsumoto . + You can redistribute it and/or modify it under either the terms of the GPL + (see COPYING.txt file), or the conditions below: + + 1. You may make and give away verbatim copies of the source form of the + software without restriction, provided that you duplicate all of the original + copyright notices and associated disclaimers. + + 2. You may modify your copy of the software in any way, provided that you do + at least ONE of the following: + + a) place your modifications in the Public Domain or otherwise make them + Freely Available, such as by posting said modifications to Usenet or an + equivalent medium, or by allowing the author to include your modifications + in the software. + + b) use the modified software only within your corporation or organization. + + c) rename any non-standard executables so the names do not conflict with + standard executables, which must also be provided. + + d) make other distribution arrangements with the author. + + 3. You may distribute the software in object code or executable form, + provided that you do at least ONE of the following: + + a) distribute the executables and library files of the software, together + with instructions (in the manual page or equivalent) on where to get the + original distribution. + + b) accompany the distribution with the machine-readable source of the + software. + + c) give non-standard executables non-standard names, with instructions on + where to get the original software distribution. + + d) make other distribution arrangements with the author. + + 4. You may modify and include the part of the software into any other + software (possibly commercial). But some files in the distribution are not + written by the author, so that they are not under this terms. + + They are gc.c(partly), utils.c(partly), regex.[ch], st.[ch] and some files + under the ./missing directory. See each file for the copying condition. + + 5. The scripts and library files supplied as input to or produced as output + from the software do not automatically fall under the copyright of the + software, but belong to whomever generated them, and may be sold + commercially, and may be aggregated with this software. + + 6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + + --- rant-0.5.8.orig/debian/bash/rant +++ rant-0.5.8/debian/bash/rant @@ -0,0 +1,63 @@ +# -*- mode:shell-script -*- + +# Programmable completion for the rant command under bash. + +# This file draws heavily on the rake and subversion files that come as standard with Bash 3. + +# Author : Russel Winder +# Version : 2006-09-21T13:34 +# Licence : LGPL + +_rant() +{ + local cur prev rantf i + + COMPREPLY=() + cur=${COMP_WORDS[COMP_CWORD]} + prev=${COMP_WORDS[COMP_CWORD-1]} + rantf="Rantfile" + + if [[ "$prev" == "-f" || "$prev" == "--rantfile" ]]; then + _filedir + return 0 + fi + + if [[ "$cur" == *=* ]]; then + prev=${cur/=*/} + cur=${cur/*=/} + if [[ "$prev" == "--rantfile=" || "$prev" == "--directory=" ]]; then + _filedir -o nospace + return 0 + fi + fi + + if [[ "$cur" == -* ]]; then + COMPREPLY=( $( compgen -W '-h --help -v --verbose -V --version -q --quiet\ + --err-commands -C '--directory=' -c --cd-parent -u --lookup\ + -f '--rantfile=' -a '--force-run=' -n --dry-run -T --tasks'\ + -- $cur )) + else + + for (( i=0; i < ${#COMP_WORDS[@]}; i++)); do + case "${COMP_WORDS[i]}" in + -f) + eval rantf=${COMP_WORDS[i+1]} + break + ;; + --rantfile=*|--rantfile\=*) + eval rantf=${COMP_WORDS[i]/*=/} + break + ;; + esac + done + + [ ! -f $rantf ] && return 0 + + COMPREPLY=( $( rant -q -f "$rantf" -T | \ + awk -F ' ' '/^rant / { if ( $2 != "#" ) print $2 }' | \ + command grep "^$cur" )) + + fi +} +complete -F _rant $filenames rant + --- rant-0.5.8.orig/debian/man/man1/rant.1 +++ rant-0.5.8/debian/man/man1/rant.1 @@ -0,0 +1,138 @@ +.\" rant.1 - rant manpage +.\" Date of last change to this manpage. +.TH RANT 1 "September 17, 2006" +.SH NAME +rant \- A flexible and portable build tool. +.SH SYNOPSIS +.B rant +.RI [OPTION]\ ...\ [TARGET]\ ... +.br +.SH DESCRIPTION +.B Striking features + +* Defining custom tasks. + +* Automated packaging, testing and RDoc generation for Ruby + applications and libraries. + +* Creation of a monolithic script tailored to the needs of a specific + project which can be used instead of an Rant installation - users + don't need to install Rant. [See man rant-import] + +* Creating gzipped tar and zip archives -- without installing + additional software. + +* Optional recognition of file changes based on MD5 checksums instead + of file modification times. + +* Dependency checking for C/C++ source files (integrated makedepend + replacement). + +* Primitive support for compiling C# sources with csc, cscc and mcs. + +.B Startup + +On startup, rant will look for a file called +.IR Rantfile +, +.IR rantfile +or +.IR root.rant +which contains the build specification (which in fact is valid Ruby +code). After reading the Rantfile(s), rant will execute the following +tasks: + +.B If at least one target was given on the commandline: + +rant will execute all tasks necessary to build all targets given on +the commandline. + +.B else: + +rant tries to build the target called "default". If no task with this +name exists, rant invokes the first defined task. + +If you want to know which task(s) will be invoked when no target is +given on the commandline, run rant with the +.IR -T +option. Example: + + $ rant -T +.br + rant # => test +.br + rant package # Create packages for distribution. +.br + rant doc # Generate documentation. +.br + rant publish-docs # Publish html docs on make.rubyfore.org. +.br + # Note: scp will prompt for rubyforge password. +.br + rant test # Run basic tests. + +The +.B first line +always shows the target that will be built if no target argument is +given. In this case, it would be the +.RI test +target. + +.PP +.SH OPTIONS +.TP + --help -h + Print a help message and exit. +.TP + --version -V + Print version of Rant and exit. +.TP + --verbose -v + Print more messages to stderr. +.TP + --quiet -q + Don't print commands. +.TP + --err-commands + Print failed commands and their exit status. +.TP + --directory DIRECTORY -C DIRECTORY + Run rant in DIRECTORY. +.TP + --cd-parent -c + With this option, Rant starts to search for an Rantfile in the + current working directory as usual, but if it doesn't find one, + it changes to the parent directory and looks there for an + Rantfile. This is repeated until an Rantfile is found or the + working directory is the root directory of the filesystem. +.TP + --look-up -u + Look in parent directories for root Rantfile. +.TP + --rantfile RANTFILE -f RANTFILE + Process RANTFILE instead of standard rantfiles. + Multiple files may be specified by repeating this option. +.TP + --force-run TARGET -a TARGET + Force rebuild of TARGET and all dependencies. +.TP + --dry-run -n + Print the names of the tasks that would be executed instead + of actually executing task actions. +.TP + --tasks -T + Show a list of all described tasks and exit. + +.SH HOMEPAGE + + +.SH AUTHOR +rant developed by Stefan Lang + +.SH COPYRIGHT +Copyright (C) 2005 Stefan Lang + +.SH SEE ALSO +rant-import(1) + +.\" vim:ft=nroff --- rant-0.5.8.orig/debian/man/man1/rant-import.1 +++ rant-0.5.8/debian/man/man1/rant-import.1 @@ -0,0 +1,47 @@ +.\" Name: Rant +.\" Program Author: Stefan Lang +.\" Author: Ralph Amissah +.\" Description: Flexible, Ruby based make +.\" License: GNU Lesser General Public License (LGPL) +.\" Notes: Process this file with +.\" groff -man -Tascii rant.1 +.\" nroff -man rant.1 | most +.TH rant\-import 1 "July 26, 2006" "version 0.5.6" "rant\-import" +.SH NAME +.B Rant \- Flexible, Ruby based make +.PP +.SH SYNOPSIS +The rant\-import command creates a monolithic rant script tailored to the needs of your project and thus removes the dependency on an Rant installation (but of course one person needs an Rant installation to run rant\-import). +.PP +Run the command with the \-\-help option to get a brief help message: +.PP + % rant-import \-\-help +.PP +Probably the easiest way to create your monolithic rant script is with the \-\-auto option: +.PP + % rant-import \-\-auto ant +.PP +This will write a monolithic rant script to the file ant in the current directory. To determine which plugins and imports your project is using, it performs step 2 of the rant command as described in doc/rant.rdoc, which means that it loads the Rantfile in the current directory. +.PP +That one command should be enough: +.PP + % ruby ant +.PP +This script has the same behaviour as the rant command. Distribute it with your project and nobody else but you needs an Rant installation. +.PP +.\"%% Further Information +.SH FURTHER INFORMATION +.PP +For more information on +.I Rant +see: +.I +.PP +.I +.PP +.SH AUTHOR +Rant is by Stefan Lang +.PP +This package is maintained by Ralph Amissah +.SH SEE +.BR rant(1) --- rant-0.5.8.orig/debian/doc/examples/debian_package/README +++ rant-0.5.8/debian/doc/examples/debian_package/README @@ -0,0 +1,55 @@ + Rantfile example for making a simple debian package of a ruby program + using git-buildpackage with debuild + + used in conjunction with the pkgrc.yml (and pkgrc.rb) example provided + (example is easily extended and works for package rant, and package diakonos), + the package default is for git branches named upstream and debian/sid, as set + in the pkgrc.yml file, and both git and git-buildpackage would need to be + installed + + * package should be in directory with package name without package version + number + + * Build files Rantfile (linked to rbuild), pkgrc.yml and pkgrc.rb should be in + directory above package directory, + e.g. for rant ls (relevant files) + pkgrc.rb pkgrc.yml Rantfile [linked to rbuild or rename rbuild Rantfile] + + * provide details of package in pkgrc.yml file [which is a yaml file] (see + example provided) + + * once these two files are in place for help on package and on possible + actions, enter: + rant + rant info + rant -T + # to build the package + rant pkg + + * to create independent rant independent ruby script: + rant-import --auto [provide name of ruby (rant exported) script] + + to create the script deb_pkg_r provided: + rant-import --auto deb_pkg_r + + NOTE this is a ruby script generated by rant, that only requires ruby to + run + [if permissions set to executable, else type: ruby deb_pkg_r ] + deb_pkg_r + deb_pkg_r info + deb_pkg_r -T + # to build the package + deb_pkg_r pkg + + Rant is a Ruby 'ant' by Stefan Lang + * Rant may be downloaded and installed from: + http://make.rubyforge.org/ + + * [NOTE should also work as a Rakefile + rake + rake -T + # to build the package + rake pkg + ] + + Notes by Ralph Amissah --- rant-0.5.8.orig/debian/doc/examples/debian_package/deb_pkg_r +++ rant-0.5.8/debian/doc/examples/debian_package/deb_pkg_r @@ -0,0 +1,3088 @@ +#!/usr/bin/env ruby + +# deb_pkg_r - Monolithic rant script, autogenerated by rant-import 0.5.8. +# +# Copyright (C) 2005 Stefan Lang +# +# This program is free software. +# You can distribute/modify this program under the terms of +# the GNU LGPL, Lesser General Public License version 2.1. + + +require 'getoptlong' + + +require 'rbconfig' + +unless Process::Status.method_defined?(:success?) # new in 1.8.2 + class Process::Status + def success?; exitstatus == 0; end + end +end +unless Regexp.respond_to? :union # new in 1.8.1 + def Regexp.union(*patterns) + return /(?!)/ if patterns.empty? + Regexp.new(patterns.join("|")) + end +end +if RUBY_VERSION < "1.8.2" + class Array + undef_method :flatten, :flatten! + def flatten + cp = self.dup + cp.flatten! + cp + end + def flatten! + res = [] + flattened = false + self.each { |e| + if e.respond_to? :to_ary + res.concat(e.to_ary) + flattened = true + else + res << e + end + } + if flattened + replace(res) + flatten! + self + end + end + end +end + +class String + def _rant_sub_ext(ext, new_ext = nil) + if new_ext + self.sub(/#{Regexp.escape ext}$/, new_ext) + else + self.sub(/(\.[^.]*$)|$/, ".#{ext}") + end + end +end + +module Rant + VERSION = '0.5.8' + + @__rant_no_value__ = Object.new.freeze + def self.__rant_no_value__ + @__rant_no_value__ + end + + module Env + OS = ::Config::CONFIG['target'] + RUBY = ::Config::CONFIG['ruby_install_name'] + RUBY_BINDIR = ::Config::CONFIG['bindir'] + RUBY_EXE = File.join(RUBY_BINDIR, RUBY + ::Config::CONFIG["EXEEXT"]) + + @@zip_bin = false + @@tar_bin = false + + if OS =~ /mswin/i + def on_windows?; true; end + else + def on_windows?; false; end + end + + def have_zip? + if @@zip_bin == false + @@zip_bin = find_bin "zip" + end + !@@zip_bin.nil? + end + def have_tar? + if @@tar_bin == false + @@tar_bin = find_bin "tar" + end + !@@tar_bin.nil? + end + def pathes + path = ENV[on_windows? ? "Path" : "PATH"] + return [] unless path + path.split(on_windows? ? ";" : ":") + end + def find_bin bin_name + if on_windows? + bin_name_exe = nil + if bin_name !~ /\.[^\.]{1,3}$/i + bin_name_exe = bin_name + ".exe" + end + pathes.each { |dir| + file = File.join(dir, bin_name) + return file if test(?f, file) + if bin_name_exe + file = File.join(dir, bin_name_exe) + return file if test(?f, file) + end + } + else + pathes.each { |dir| + file = File.join(dir, bin_name) + return file if test(?x, file) + } + end + nil + end + def shell_path path + if on_windows? + path = path.tr("/", "\\") + if path.include? ' ' + '"' + path + '"' + else + path + end + else + if path.include? ' ' + "'" + path + "'" + else + path + end + end + end + extend self + end # module Env + + module Sys + def sp(arg) + if arg.respond_to? :to_ary + arg.to_ary.map{ |e| sp e }.join(' ') + else + _escaped_path arg + end + end + def escape(arg) + if arg.respond_to? :to_ary + arg.to_ary.map{ |e| escape e }.join(' ') + else + _escaped arg + end + end + if Env.on_windows? + def _escaped_path(path) + _escaped(path.to_s.tr("/", "\\")) + end + def _escaped(arg) + sarg = arg.to_s + return sarg unless sarg.include?(" ") + sarg << "\\" if sarg[-1].chr == "\\" + "\"#{sarg}\"" + end + def regular_filename(fn) + fn.to_str.tr("\\", "/").gsub(%r{/{2,}}, "/") + end + else + def _escaped_path(path) + path.to_s.gsub(/(?=\s)/, "\\") + end + alias _escaped _escaped_path + def regular_filename(fn) + fn.to_str.gsub(%r{/{2,}}, "/") + end + end + private :_escaped_path + private :_escaped + def split_all(path) + names = regular_filename(path).split(%r{/}) + names[0] = "/" if names[0] && names[0].empty? + names + end + extend self + end # module Sys + + + ROOT_RANTFILE = "root.rant" + SUB_RANTFILE = "sub.rant" + RANTFILES = [ "Rantfile", "rantfile", ROOT_RANTFILE ] + + CODE_IMPORTS = [] + + class RantAbortException < StandardError + end + + class RantDoneException < StandardError + end + + class Error < StandardError + end + + module Generators + end + + module RantVar + + class Error < Rant::Error + end + + class ConstraintError < Error + + attr_reader :constraint, :val + + def initialize(constraint, val, msg = nil) + @msg = msg + @constraint = constraint + @val = val + end + + def message + val_desc = @val.inspect + val_desc[7..-1] = "..." if val_desc.length > 10 + "#{val_desc} doesn't match constraint: #@constraint" + end + end + + class NotAConstraintFactoryError < Error + attr_reader :obj + def initialize(obj, msg = nil) + @msg = msg + @obj = obj + end + def message + obj_desc = @obj.inspect + obj_desc[7..-1] = "..." if obj_desc.length > 10 + "#{obj_desc} is not a valid constraint factory" + end + end + + class InvalidVidError < Error + def initialize(vid, msg = nil) + @msg = msg + @vid = vid + end + def message + vid_desc = @vid.inspect + vid_desc[7..-1] = "..." if vid_desc.length > 10 + "#{vid_desc} is not a valid var identifier" + end + end + + class InvalidConstraintError < Error + end + + class QueryError < Error + end + + class Space + + @@env_ref = Object.new + + def initialize + @store = {} + @constraints = {} + end + + def query(*args, &block) + case args.size + when 0 + raise QueryError, "no arguments", caller + when 1 + arg = args.first + if Hash === arg + if arg.size == 1 + arg.each { |k,v| + self[k] = v if self[k].nil? + } + self + else + init_all arg + end + else + self[arg] + end + when 2, 3 + vid, cf, val = *args + constrain vid, + get_factory(cf).rant_constraint + self[vid] = val if val + else + raise QueryError, "too many arguments" + end + end + + def restrict vid, ct, *ct_args + if vid.respond_to? :to_ary + vid.to_ary.each { |v| restrict(v, ct, *ct_args) } + else + constrain vid, + get_factory(ct).rant_constraint(*ct_args) + end + self + end + + def get_factory id + if String === id || Symbol === id + id = Constraints.const_get(id) rescue nil + end + unless id.respond_to? :rant_constraint + raise NotAConstraintFactoryError.new(id), caller + end + id + end + private :get_factory + + def [](vid) + vid = RantVar.valid_vid vid + val = @store[vid] + val.equal?(@@env_ref) ? ENV[vid] : val + end + + def []=(vid, val) + vid = RantVar.valid_vid(vid) + c = @constraints[vid] + if @store[vid] == @@env_ref + ENV[vid] = c ? c.filter(val) : val + else + @store[vid] = c ? c.filter(val) : val + end + end + + def env(*vars) + vars.flatten.each { |var| + vid = RantVar.valid_vid(var) + cur_val = @store[vid] + next if cur_val == @@env_ref + ENV[vid] = cur_val unless cur_val.nil? + @store[vid] = @@env_ref + } + nil + end + + def set_all hash + unless Hash === hash + raise QueryError, + "set_all argument has to be a hash" + end + hash.each_pair { |k, v| + self[k] = v + } + end + + def init_all hash + unless Hash === hash + raise QueryError, + "init_all argument has to be a hash" + end + hash.each_pair { |k, v| + self[k] = v if self[k].nil? + } + end + + def constrain vid, constraint + vid = RantVar.valid_vid(vid) + unless RantVar.valid_constraint? constraint + raise InvalidConstraintError, constraint + end + @constraints[vid] = constraint + if @store.member? vid + begin + val = @store[vid] + @store[vid] = constraint.filter(@store[vid]) + rescue + @store[vid] = constraint.default + raise ConstraintError.new(constraint, val) + end + else + @store[vid] = constraint.default + end + end + + def has_var?(vid) + !self[vid].nil? + end + + def _set(vid, val) #:nodoc: + @store[vid] = val + end + + def _get(vid) #:nodoc: + @store[vid] + end + + def _init(vid, val) #:nodoc: + @store[vid] ||= val + end + + end # class Space + + module Constraint + def matches? val + filter val + true + rescue + return false + end + end + + def valid_vid(obj) + case obj + when String; obj + when Symbol; obj.to_s + else + if obj.respond_to? :to_str + obj.to_str + else + raise InvalidVidError.new(obj) + end + end + end + + def valid_constraint?(obj) + obj.respond_to?(:filter) && + obj.respond_to?(:matches?) && + obj.respond_to?(:default) + end + + module_function :valid_constraint?, :valid_vid + + module Constraints + class AutoList + include Constraint + class << self + alias rant_constraint new + end + def filter(val) + if val.respond_to? :to_ary + val.to_ary + elsif val.nil? + raise ConstraintError.new(self, val) + else + [val] + end + end + def default + [] + end + def to_s + "list or single, non-nil value" + end + end + end # module Constraints + end # module RantVar +end # module Rant + + +require 'fileutils' + + +module Rant + def FileList(arg) + if arg.respond_to?(:to_rant_filelist) + arg.to_rant_filelist + elsif arg.respond_to?(:to_ary) + FileList.new(arg.to_ary) + else + raise TypeError, + "cannot convert #{arg.class} into Rant::FileList" + end + end + module_function :FileList + class FileList + include Enumerable + + ESC_SEPARATOR = Regexp.escape(File::SEPARATOR) + ESC_ALT_SEPARATOR = File::ALT_SEPARATOR ? + Regexp.escape(File::ALT_SEPARATOR) : nil + + class << self + def [](*patterns) + new.hide_dotfiles.include(*patterns) + end + def glob(*patterns) + fl = new.hide_dotfiles.ignore(".", "..").include(*patterns) + if block_given? then yield fl else fl end + end + def glob_all(*patterns) + fl = new.ignore(".", "..").include(*patterns) + if block_given? then yield fl else fl end + end + end + + def initialize(store = []) + @pending = false + @def_glob_dotfiles = true + @items = store + @ignore_rx = nil + @keep = {} + @actions = [] + end + alias _object_dup dup + private :_object_dup + def dup + c = _object_dup + c.items = @items.dup + c.actions = @actions.dup + c.ignore_rx = @ignore_rx.dup if @ignore_rx + c.instance_variable_set(:@keep, @keep.dup) + c + end + def copy + c = _object_dup + c.items = @items.map { |entry| entry.dup } + c.actions = @actions.dup + c.ignore_rx = @ignore_rx.dup if @ignore_rx + h_keep = {} + @keep.each_key { |entry| h_keep[entry] = true } + c.instance_variable_set(:@keep, h_keep) + c + end + def glob_dotfiles? + @def_glob_dotfiles + end + def glob_dotfiles=(flag) + @def_glob_dotfiles = flag ? true : false + end + def hide_dotfiles + @def_glob_dotfiles = false + self + end + def glob_dotfiles + @def_glob_dotfiles = true + self + end + + protected + attr_accessor :actions, :items + attr_accessor :pending + attr_accessor :ignore_rx + + public + def each(&block) + resolve if @pending + @items.each(&block) + self + end + def to_ary + resolve if @pending + @items + end + alias to_a to_ary + alias entries to_ary # entries: defined in Enumerable + def to_rant_filelist + self + end + def +(other) + if other.respond_to? :to_rant_filelist + c = other.to_rant_filelist.dup + c.actions.concat(@actions) + c.items.concat(@items) + c.pending = !c.actions.empty? + c + elsif other.respond_to? :to_ary + c = dup + c.actions << + [:apply_ary_method_1, :concat, other.to_ary.dup] + c.pending = true + c + else + raise TypeError, + "cannot add #{other.class} to Rant::FileList" + end + end + def <<(file) + @actions << [:apply_ary_method_1, :push, file] + @keep[file] = true + @pending = true + self + end + def keep(entry) + @keep[entry] = true + @items << entry + self + end + def concat(ary) + if @pending + ary = ary.to_ary.dup + @actions << [:apply_ary_method_1, :concat, ary] + else + ix = ignore_rx and ary = ary.to_ary.reject { |f| f =~ ix } + @items.concat(ary) + end + self + end + def size + resolve if @pending + @items.size + end + alias length size + def empty? + resolve if @pending + @items.empty? + end + def join(sep = ' ') + resolve if @pending + @items.join(sep) + end + def pop + resolve if @pending + @items.pop + end + def push(entry) + resolve if @pending + @items.push(entry) if entry !~ ignore_rx + self + end + def shift + resolve if @pending + @items.shift + end + def unshift(entry) + resolve if @pending + @items.unshift(entry) if entry !~ ignore_rx + self + end +if Object.method_defined?(:fcall) || Object.method_defined?(:funcall) # in Ruby 1.9 like __send__ + @@__send_private__ = Object.method_defined?(:fcall) ? :fcall : :funcall + def resolve + @pending = false + @actions.each{ |action| self.__send__(@@__send_private__, *action) }.clear + ix = ignore_rx + if ix + @items.reject! { |f| f =~ ix && !@keep[f] } + end + self + end +else + def resolve + @pending = false + @actions.each{ |action| self.__send__(*action) }.clear + ix = ignore_rx + if ix + @items.reject! { |f| f =~ ix && !@keep[f] } + end + self + end +end + def include(*pats) + @def_glob_dotfiles ? glob_all(*pats) : glob_unix(*pats) + end + alias glob include + def glob_unix(*patterns) + patterns.flatten.each { |pat| + @actions << [:apply_glob_unix, pat] + } + @pending = true + self + end + def glob_all(*patterns) + patterns.flatten.each { |pat| + @actions << [:apply_glob_all, pat] + } + @pending = true + self + end + if RUBY_VERSION < "1.8.2" + FN_DOTFILE_RX_ = ESC_ALT_SEPARATOR ? + /(^|(#{ESC_SEPARATOR}|#{ESC_ALT_SEPARATOR})+)\..* + ((#{ESC_SEPARATOR}|#{ESC_ALT_SEPARATOR})+|$)/x : + /(^|#{ESC_SEPARATOR}+)\..* (#{ESC_SEPARATOR}+|$)/x + def apply_glob_unix(pattern) + inc_files = Dir.glob(pattern) + unless pattern =~ /(^|\/)\./ + inc_files.reject! { |fn| fn =~ FN_DOTFILE_RX_ } + end + @items.concat(inc_files) + end + else + def apply_glob_unix(pattern) + @items.concat(Dir.glob(pattern)) + end + end + private :apply_glob_unix + def apply_glob_all(pattern) + @items.concat(Dir.glob(pattern, File::FNM_DOTMATCH)) + end + private :apply_glob_all + def exclude(*patterns) + patterns.each { |pat| + if Regexp === pat + @actions << [:apply_exclude_rx, pat] + else + @actions << [:apply_exclude, pat] + end + } + @pending = true + self + end + def ignore(*patterns) + patterns.each { |pat| + add_ignore_rx(Regexp === pat ? pat : mk_all_rx(pat)) + } + @pending = true + self + end + def add_ignore_rx(rx) + @ignore_rx = + if @ignore_rx + Regexp.union(@ignore_rx, rx) + else + rx + end + end + private :add_ignore_rx + def apply_exclude(pattern) + @items.reject! { |elem| + File.fnmatch?(pattern, elem, File::FNM_DOTMATCH) && !@keep[elem] + } + end + private :apply_exclude + def apply_exclude_rx(rx) + @items.reject! { |elem| + elem =~ rx && !@keep[elem] + } + end + private :apply_exclude_rx + def exclude_name(*names) + names.each { |name| + @actions << [:apply_exclude_rx, mk_all_rx(name)] + } + @pending = true + self + end + alias shun exclude_name + if File::ALT_SEPARATOR + def mk_all_rx(file) + /(^|(#{ESC_SEPARATOR}|#{ESC_ALT_SEPARATOR})+)#{Regexp.escape(file)} + ((#{ESC_SEPARATOR}|#{ESC_ALT_SEPARATOR})+|$)/x + end + else + def mk_all_rx(file) + /(^|#{ESC_SEPARATOR}+)#{Regexp.escape(file)} + (#{ESC_SEPARATOR}+|$)/x + end + end + private :mk_all_rx + def exclude_path(*patterns) + patterns.each { |pat| + @actions << [:apply_exclude_path, pat] + } + @pending = true + self + end + def apply_exclude_path(pattern) + flags = File::FNM_DOTMATCH|File::FNM_PATHNAME + @items.reject! { |elem| + File.fnmatch?(pattern, elem, flags) && !@keep[elem] + } + end + private :apply_exclude + def select(&block) + d = dup + d.actions << [:apply_select, block] + d.pending = true + d + end + alias find_all select + def apply_select blk + @items = @items.select(&blk) + end + private :apply_select + def map(&block) + d = dup + d.actions << [:apply_ary_method, :map!, block] + d.pending = true + d + end + alias collect map + def sub_ext(ext, new_ext=nil) + map { |f| f._rant_sub_ext ext, new_ext } + end + def ext(ext_str) + sub_ext(ext_str) + end + def arglist + Rant::Sys.sp to_ary + end + alias to_s arglist + alias object_inspect inspect + def uniq! + @actions << [:apply_ary_method, :uniq!] + @pending = true + self + end + def sort! + @actions << [:apply_ary_method, :sort!] + @pending = true + self + end + def map!(&block) + @actions << [:apply_ary_method, :map!, block] + @pending = true + self + end + def reject!(&block) + @actions << [:apply_ary_method, :reject!, block] + @pending = true + self + end + private + def apply_ary_method(meth, block=nil) + @items.send meth, &block + end + def apply_ary_method_1(meth, arg1, block=nil) + @items.send meth, arg1, &block + end + end # class FileList +end # module Rant + +if RUBY_VERSION == "1.8.3" + module FileUtils + METHODS = singleton_methods - %w(private_module_function + commands options have_option? options_of collect_method) + module Verbose + class << self + public(*::FileUtils::METHODS) + end + public(*::FileUtils::METHODS) + end + end +end + +if RUBY_VERSION < "1.8.1" + module FileUtils + undef_method :fu_list + def fu_list(arg) + arg.respond_to?(:to_ary) ? arg.to_ary : [arg] + end + end +end + +module Rant + class RacFileList < FileList + + attr_reader :subdir + attr_reader :basedir + + def initialize(rac, store = []) + super(store) + @rac = rac + @subdir = @rac.current_subdir + @basedir = Dir.pwd + @ignore_hash = nil + @add_ignore_args = [] + update_ignore_rx + end + def dup + c = super + c.instance_variable_set( + :@add_ignore_args, @add_ignore_args.dup) + c + end + def copy + c = super + c.instance_variable_set( + :@add_ignore_args, @add_ignore_args.map { |e| e.dup }) + c + end + alias filelist_ignore ignore + def ignore(*patterns) + @add_ignore_args.concat patterns + self + end + def ignore_rx + update_ignore_rx + @ignore_rx + end + alias filelist_resolve resolve + def resolve + Sys.cd(@basedir) { filelist_resolve } + end + def each_cd(&block) + old_pwd = Dir.pwd + Sys.cd(@basedir) + filelist_resolve if @pending + @items.each(&block) + ensure + Sys.cd(old_pwd) + end + private + def update_ignore_rx + ri = @rac.var[:ignore] + ri = ri ? (ri + @add_ignore_args) : @add_ignore_args + rh = ri.hash + unless rh == @ignore_hash + @ignore_rx = nil + filelist_ignore(*ri) + @ignore_hash = rh + end + end + end # class RacFileList + + class MultiFileList + + attr_reader :cur_list + + def initialize(rac) + @rac = rac + @cur_list = RacFileList.new(@rac) + @lists = [@cur_list] + end + + def each_entry(&block) + @lists.each { |list| + list.each_cd(&block) + } + end + + def add(filelist) + @cur_list = filelist + @lists << filelist + self + end + + def method_missing(sym, *args, &block) + if @cur_list && @cur_list.respond_to?(sym) + if @cur_list.subdir == @rac.current_subdir + @cur_list.send(sym, *args, &block) + else + add(RacFileList.new(@rac)) + @cur_list.send(sym, *args, &block) + end + else + super + end + end + end # class MultiFileList + + class CommandError < StandardError + attr_reader :cmd + attr_reader :status + def initialize(cmd, status=nil, msg=nil) + @msg = msg + @cmd = cmd + @status = status + end + def message + if !@msg && cmd + if status + "Command failed with status #{status.exitstatus}:\n" + + "[#{cmd}]" + else + "Command failed:\n[#{cmd}]" + end + else + @msg + end + end + end + + module Sys + include ::FileUtils::Verbose + + @symlink_supported = true + class << self + attr_accessor :symlink_supported + end + + def fu_output_message(msg) #:nodoc: + end + private :fu_output_message + + def fu_each_src_dest(src, *rest) + src = src.to_ary if src.respond_to? :to_ary + super(src, *rest) + end + private :fu_each_src_dest + + def sh(*cmd_args, &block) + cmd_args.flatten! + cmd = cmd_args.join(" ") + fu_output_message cmd + success = system(*cmd_args) + if block_given? + block[$?] + elsif !success + raise CommandError.new(cmd, $?) + end + end + + def ruby(*args, &block) + if args.empty? + sh(Env::RUBY_EXE, '', &block) + else + sh(args.unshift(Env::RUBY_EXE), &block) + end + end + def cd(dir, &block) + fu_output_message "cd #{dir}" + orig_pwd = Dir.pwd + Dir.chdir dir + if block + begin + block.arity == 0 ? block.call : block.call(Dir.pwd) + ensure + fu_output_message "cd -" + Dir.chdir orig_pwd + end + else + self + end + end + + def safe_ln(src, dest) + dest = dest.to_str + src = src.respond_to?(:to_ary) ? src.to_ary : src.to_str + unless Sys.symlink_supported + cp(src, dest) + else + begin + ln(src, dest) + rescue Exception # SystemCallError # Errno::EOPNOTSUPP + Sys.symlink_supported = false + cp(src, dest) + end + end + end + + def ln_f(src, dest) + ln(src, dest, :force => true) + end + + def split_path(str) + str.split(Env.on_windows? ? ";" : ":") + end + + if Env.on_windows? + def root_dir?(path) + path == "/" || path == "\\" || + path =~ %r{\A[a-zA-Z]+:(\\|/)\Z} + end + def absolute_path?(path) + path =~ %r{\A([a-zA-Z]+:)?(/|\\)} + end + else + def root_dir?(path) + path == "/" + end + def absolute_path?(path) + path =~ %r{\A/} + end + end + + extend self + + if RUBY_VERSION >= "1.8.4" # needed by 1.9.0, too + class << self + public(*::FileUtils::METHODS) + end + public(*::FileUtils::METHODS) + end + + end # module Sys + + class SysObject + include Sys + def initialize(rant) + @rant = rant or + raise ArgumentError, "rant application required" + end + def ignore(*patterns) + @rant.var[:ignore].concat(patterns) + nil + end + def filelist(arg = Rant.__rant_no_value__) + if Rant.__rant_no_value__.equal?(arg) + RacFileList.new(@rant) + elsif arg.respond_to?(:to_rant_filelist) + arg.to_rant_filelist + elsif arg.respond_to?(:to_ary) + RacFileList.new(@rant, arg.to_ary) + else + raise TypeError, + "cannot convert #{arg.class} into Rant::FileList" + end + end + def [](*patterns) + RacFileList.new(@rant).hide_dotfiles.include(*patterns) + end + def glob(*patterns, &block) + fl = RacFileList.new(@rant).hide_dotfiles.include(*patterns) + fl.ignore(".", "..") + if block_given? then yield fl else fl end + end + def glob_all(*patterns, &block) + fl = RacFileList.new(@rant).include(*patterns) + fl.ignore(".", "..") # use case: "*.*" as pattern + if block_given? then yield fl else fl end + end + def expand_path(path) + File.expand_path(@rant.project_to_fs_path(path)) + end + private + def fu_output_message(cmd) + @rant.cmd_msg cmd + end + end + + + class TaskFail < StandardError + def initialize(task, orig, msg) + @task = task + @orig = orig + @msg = msg + end + def exception + self + end + def task + @task + end + def tname + @task ? @task.name : nil + end + def orig + @orig + end + def msg + @msg + end + end + + class Rantfile + attr_reader :tasks, :path + attr_accessor :project_subdir + def initialize(path) + @path = path or raise ArgumentError, "path required" + @tasks = [] + @project_subdir = nil + end + alias to_s path + alias to_str path + end # class Rantfile + + module Node + + INVOKE_OPT = {}.freeze + + T0 = Time.at(0).freeze + + attr_reader :name + attr_reader :rac + attr_accessor :description + attr_accessor :rantfile + attr_accessor :line_number + attr_accessor :project_subdir + + def initialize + @description = nil + @rantfile = nil + @line_number = nil + @run = false + @project_subdir = "" + @success = nil + end + + def reference_name + sd = rac.current_subdir + case sd + when ""; full_name + when project_subdir; name + else "@#{full_name}".sub(/^@#{Regexp.escape sd}\//, '') + end + end + + alias to_s reference_name + alias to_rant_target name + + def full_name + sd = project_subdir + sd.empty? ? name : File.join(sd, name) + end + + def ch + {:file => rantfile.to_str, :ln => line_number} + end + + def goto_task_home + @rac.goto_project_dir project_subdir + end + + def file_target? + false + end + + def done? + @success + end + + def needed? + invoke(:needed? => true) + end + + def run? + @run + end + + def invoke(opt = INVOKE_OPT) + return circular_dep if run? + @run = true + begin + return !done? if opt[:needed?] + self.run if !done? + @success = true + ensure + @run = false + end + end + + def fail msg = nil, orig = nil + raise TaskFail.new(self, orig, msg) + end + + def each_target + end + + def has_actions? + defined? @block and @block + end + + def dry_run + text = "Executing #{name.dump}" + text << " [NOOP]" unless has_actions? + @rac.cmd_msg text + action_descs.each { |ad| + @rac.cmd_print " - " + @rac.cmd_msg ad.sub(/\n$/, '').gsub(/\n/, "\n ") + } + end + + private + def run + goto_task_home + return if @rac.running_task(self) + return unless has_actions? + @receiver.pre_run(self) if defined? @receiver and @receiver + @block.arity == 0 ? @block.call : @block[self] if @block + end + + def action_descs + descs = [] + if defined? @receiver and @receiver + descs.concat(@receiver.pre_action_descs) + end + @block ? descs << action_block_desc : descs + end + + def action_block_desc + @block.inspect =~ /^#$/i + fn, ln = $1, $2 + "Ruby Proc at #{fn.sub(/^#{Regexp.escape @rac.rootdir}\//, '')}:#{ln}" + end + + def circular_dep + rac.warn_msg "Circular dependency on task `#{full_name}'." + false + end + end # module Node + + + def self.init_import_nodes__default(rac, *rest) + rac.node_factory = DefaultNodeFactory.new + end + + class DefaultNodeFactory + def new_task(rac, name, pre, blk) + Task.new(rac, name, pre, &blk) + end + def new_file(rac, name, pre, blk) + FileTask.new(rac, name, pre, &blk) + end + def new_dir(rac, name, pre, blk) + DirTask.new(rac, name, pre, &blk) + end + def new_source(rac, name, pre, blk) + SourceNode.new(rac, name, pre, &blk) + end + def new_custom(rac, name, pre, blk) + UserTask.new(rac, name, pre, &blk) + end + def new_auto_subfile(rac, name, pre, blk) + AutoSubFileTask.new(rac, name, pre, &blk) + end + end + + class Task + include Node + + attr_accessor :receiver + + def initialize(rac, name, prerequisites = [], &block) + super() + @rac = rac or raise ArgumentError, "rac not given" + @name = name or raise ArgumentError, "name not given" + @pre = prerequisites || [] + @pre_resolved = false + @block = block + @run = false + @receiver = nil + end + + def prerequisites + @pre.collect { |pre| pre.to_s } + end + alias deps prerequisites + + def source + @pre.first.to_s + end + + def has_actions? + @block or @receiver && @receiver.has_pre_action? + end + + def <<(pre) + @pre_resolved = false + @pre << pre + end + + def invoked? + !@success.nil? + end + + def fail? + @success == false + end + + def enhance(deps = nil, &blk) + if deps + @pre_resolved = false + @pre.concat deps + end + if @block + if blk + first_block = @block + @block = lambda { |t| + first_block[t] + blk[t] + } + end + else + @block = blk + end + end + + def invoke(opt = INVOKE_OPT) + return circular_dep if @run + @run = true + begin + return if done? + internal_invoke opt + ensure + @run = false + end + end + + def internal_invoke(opt, ud_init = true) + goto_task_home + update = ud_init || opt[:force] + dep = nil + uf = false + each_dep { |dep| + if dep.respond_to? :timestamp + handle_timestamped(dep, opt) && update = true + elsif Node === dep + handle_node(dep, opt) && update = true + else + dep, uf = handle_non_node(dep, opt) + uf && update = true + dep + end + } + if @receiver + goto_task_home + update = true if @receiver.update?(self) + end + return update if opt[:needed?] + run if update + @success = true + update + rescue StandardError => e + @success = false + self.fail(nil, e) + end + private :internal_invoke + + def handle_node(dep, opt) + dep.invoke opt + end + + def handle_timestamped(dep, opt) + dep.invoke opt + end + + def handle_non_node(dep, opt) + @rac.err_msg "Unknown task `#{dep}',", + "referenced in `#{rantfile.path}', line #{@line_number}!" + self.fail + end + + def each_dep + t = nil + if @pre_resolved + return @pre.each { |t| yield(t) } + end + my_full_name = full_name + my_project_subdir = project_subdir + @pre.map! { |t| + if Node === t + if t.full_name == my_full_name + nil + else + yield(t) + t + end + else + t = t.to_s if Symbol === t + if t == my_full_name #TODO + nil + else + selection = @rac.resolve t, + my_project_subdir + if selection.empty? + yield(t) + else + selection.each { |st| yield(st) } + selection + end + end + end + } + if @pre.kind_of? Rant::FileList + @pre.resolve + else + @pre.flatten! + @pre.compact! + end + @pre_resolved = true + end + end # class Task + + class UserTask < Task + + def initialize(*args) + super + @block = nil + @needed = nil + @target_files = nil + yield self if block_given? + end + + def act(&block) + @block = block + end + + def needed(&block) + @needed = block + end + + def file_target? + @target_files and @target_files.include? @name + end + + def each_target(&block) + goto_task_home + @target_files.each(&block) if @target_files + end + + def file_target(*args) + args.flatten! + args << @name if args.empty? + if @target_files + @target_files.concat(args) + else + @target_files = args + end + end + + def invoke(opt = INVOKE_OPT) + return circular_dep if @run + @run = true + begin + return if done? + internal_invoke(opt, ud_init_by_needed) + ensure + @run = false + end + end + + private + def ud_init_by_needed + if @needed + goto_task_home + @needed.arity == 0 ? @needed.call : @needed[self] + end + end + end # class UserTask + + class FileTask < Task + + def initialize(*args) + super + @ts = T0 + end + + def file_target? + true + end + + def invoke(opt = INVOKE_OPT) + return circular_dep if @run + @run = true + begin + return if done? + goto_task_home + if File.exist? @name + @ts = File.mtime @name + internal_invoke opt, false + else + @ts = T0 + internal_invoke opt, true + end + ensure + @run = false + end + end + + def timestamp(opt = INVOKE_OPT) + File.exist?(@name) ? File.mtime(@name) : T0 + end + + def handle_node(dep, opt) + return true if dep.file_target? && dep.invoke(opt) + if File.exist? dep.name + File.mtime(dep.name) > @ts + elsif !dep.file_target? + @rac.err_msg @rac.pos_text(rantfile.path, line_number), + "in prerequisites: no such file: `#{dep.full_name}'" + self.fail + end + end + + def handle_timestamped(dep, opt) + return true if dep.invoke opt + dep.timestamp(opt) > @ts + end + + def handle_non_node(dep, opt) + goto_task_home # !!?? + unless File.exist? dep + @rac.err_msg @rac.pos_text(rantfile.path, line_number), + "in prerequisites: no such file or task: `#{dep}'" + self.fail + end + [dep, File.mtime(dep) > @ts] + end + + def each_target + goto_task_home + yield name + end + end # class FileTask + + module AutoInvokeDirNode + private + def run + goto_task_home + return if @rac.running_task(self) + dir = File.dirname(name) + @rac.build dir unless dir == "." || dir == "/" + return unless @block + @block.arity == 0 ? @block.call : @block[self] + end + end + + class AutoSubFileTask < FileTask + include AutoInvokeDirNode + end + + class DirTask < Task + + def initialize(*args) + super + @ts = T0 + @isdir = nil + end + + def invoke(opt = INVOKE_OPT) + return circular_dep if @run + @run = true + begin + return if done? + goto_task_home + @isdir = test(?d, @name) + if @isdir + @ts = @block ? test(?M, @name) : Time.now + internal_invoke opt, false + else + @ts = T0 + internal_invoke opt, true + end + ensure + @run = false + end + end + + def file_target? + true + end + + def handle_node(dep, opt) + return true if dep.file_target? && dep.invoke(opt) + if File.exist? dep.name + File.mtime(dep.name) > @ts + elsif !dep.file_target? + @rac.err_msg @rac.pos_text(rantfile.path, line_number), + "in prerequisites: no such file: `#{dep.full_name}'" + self.fail + end + end + + def handle_timestamped(dep, opt) + return @block if dep.invoke opt + @block && dep.timestamp(opt) > @ts + end + + def handle_non_node(dep, opt) + goto_task_home + unless File.exist? dep + @rac.err_msg @rac.pos_text(rantfile.path, line_number), + "in prerequisites: no such file or task: `#{dep}'" + self.fail + end + [dep, @block && File.mtime(dep) > @ts] + end + + def run + return if @rac.running_task(self) + @rac.sys.mkdir @name unless @isdir + if @block + @block.arity == 0 ? @block.call : @block[self] + goto_task_home + @rac.sys.touch @name + end + end + + def each_target + goto_task_home + yield name + end + end # class DirTask + + class SourceNode + include Node + def initialize(rac, name, prerequisites = []) + super() + @rac = rac + @name = name or raise ArgumentError, "name not given" + @pre = prerequisites + @run = false + @ts = nil + end + def prerequisites + @pre + end + def timestamp(opt = INVOKE_OPT) + return @ts if @ts + goto_task_home + if File.exist?(@name) + @ts = File.mtime @name + else + rac.abort_at(ch, "SourceNode: no such file -- #@name") + end + sd = project_subdir + @pre.each { |f| + nodes = rac.resolve f, sd + if nodes.empty? + if File.exist? f + mtime = File.mtime f + @ts = mtime if mtime > @ts + else + rac.abort_at(ch, + "SourceNode: no such file -- #{f}") + end + else + nodes.each { |node| + node.invoke(opt) + if node.respond_to? :timestamp + node_ts = node.timestamp(opt) + goto_task_home + @ts = node_ts if node_ts > @ts + else + rac.abort_at(ch, + "SourceNode can't depend on #{node.name}") + end + } + end + } + @ts + end + def invoke(opt = INVOKE_OPT) + false + end + def related_sources + @pre + end + end # class SourceNode + + module Generators + class Task + def self.rant_gen(rac, ch, args, &block) + unless args.size == 1 + rac.abort("Task takes only one argument " + + "which has to be like one given to the " + + "`task' function") + end + rac.prepare_task(args.first, nil, ch) { |name,pre,blk| + rac.node_factory.new_custom(rac, name, pre, block) + } + end + end + class Directory + def self.rant_gen(rac, ch, args, &block) + case args.size + when 1 + name, pre = rac.normalize_task_arg(args.first, ch) + self.task(rac, ch, name, pre, &block) + when 2 + basedir = args.shift + if basedir.respond_to? :to_str + basedir = basedir.to_str + else + rac.abort_at(ch, + "Directory: basedir argument has to be a string.") + end + name, pre = rac.normalize_task_arg(args.first, ch) + self.task(rac, ch, name, pre, basedir, &block) + else + rac.abort_at(ch, "Directory takes one argument, " + + "which should be like one given to the `task' command.") + end + end + + def self.task(rac, ch, name, prerequisites=[], basedir=nil, &block) + dirs = ::Rant::Sys.split_all(name) + if dirs.empty? + rac.abort_at(ch, + "Not a valid directory name: `#{name}'") + end + path = basedir + last_task = nil + task_block = nil + desc_for_last = rac.pop_desc + dirs.each { |dir| + pre = [path] + pre.compact! + if dir.equal?(dirs.last) + rac.cx.desc desc_for_last + + dp = prerequisites.dup + pre.each { |elem| dp << elem } + pre = dp + + task_block = block + end + path = path.nil? ? dir : File.join(path, dir) + last_task = rac.prepare_task({:__caller__ => ch, + path => pre}, task_block) { |name,pre,blk| + rac.node_factory.new_dir(rac, name, pre, blk) + } + } + last_task + end + end # class Directory + class SourceNode + def self.rant_gen(rac, ch, args) + unless args.size == 1 + rac.abort_at(ch, "SourceNode takes one argument.") + end + if block_given? + rac.abort_at(ch, "SourceNode doesn't take a block.") + end + rac.prepare_task(args.first, nil, ch) { |name, pre, blk| + rac.node_factory.new_source(rac, name, pre, blk) + } + end + end + class Rule + def self.rant_gen(rac, ch, args, &block) + unless args.size == 1 + rac.abort_at(ch, "Rule takes only one argument.") + end + rac.abort_at(ch, "Rule: block required.") unless block + arg = args.first + target = nil + src_arg = nil + if Symbol === arg + target = ".#{arg}" + elsif arg.respond_to? :to_str + target = arg.to_str + elsif Regexp === arg + target = arg + elsif Hash === arg && arg.size == 1 + arg.each_pair { |target, src_arg| } + src_arg = src_arg.to_str if src_arg.respond_to? :to_str + target = target.to_str if target.respond_to? :to_str + src_arg = ".#{src_arg}" if Symbol === src_arg + target = ".#{target}" if Symbol === target + else + rac.abort_at(ch, "Rule argument " + + "has to be a hash with one key-value pair.") + end + esc_target = nil + target_rx = case target + when String + esc_target = Regexp.escape(target) + /#{esc_target}$/ + when Regexp + target + else + rac.abort_at(ch, "rule target has " + + "to be a string or regular expression") + end + src_proc = case src_arg + when String, Array + unless String === target + rac.abort(ch, "rule target has to be " + + "a string if source is a string") + end + if src_arg.kind_of? String + lambda { |name| + name.sub(/#{esc_target}$/, src_arg) + } + else + lambda { |name| + src_arg.collect { |s_src| + s_src = ".#{s_src}" if Symbol === s_src + name.sub(/#{esc_target}$/, s_src) + } + } + end + when Proc; src_arg + when nil; lambda { |name| [] } + else + rac.abort_at(ch, "rule source has to be a " + + "String, Array or Proc") + end + rac.resolve_hooks << + (block.arity == 2 ? Hook : FileHook).new( + rac, ch, target_rx, src_proc, block) + nil + end + class Hook + attr_accessor :target_rx + def initialize(rant, ch, target_rx, src_proc, block) + @rant = rant + @ch = ch + @target_rx = target_rx + @src_proc = src_proc + @block = block + end + def call(target, rel_project_dir) + if @target_rx =~ target + have_src = true + src = @src_proc[target] + if src.respond_to? :to_ary + have_src = src.to_ary.all? { |s| + have_src?(rel_project_dir, s) + } + else + have_src = have_src?(rel_project_dir, src) + end + if have_src + create_nodes(rel_project_dir, target, src) + end + end + end + alias [] call + private + def have_src?(rel_project_dir, name) + return true unless + @rant.rec_save_resolve(name, self, rel_project_dir).empty? + test(?e, @rant.abs_path(rel_project_dir, name)) + end + def create_nodes(rel_project_dir, target, deps) + @rant.goto_project_dir rel_project_dir + case nodes = @block[target, deps] + when Array; nodes + when Node; [nodes] + else + @rant.abort_at(@ch, "Block has to " + + "return Node or array of Nodes.") + end + end + end + class FileHook < Hook + private + def have_src?(rel_project_dir, name) + test(?e, @rant.abs_path(rel_project_dir, name)) or + @rant.rec_save_resolve(name, self, rel_project_dir + ).any? { |t| t.file_target? } + end + def create_nodes(rel_project_dir, target, deps) + @rant.goto_project_dir rel_project_dir + t = @rant.file(:__caller__ => @ch, + target => deps, &@block) + [t] + end + end + end # class Rule + class Action + def self.rant_gen(rac, ch, args, &block) + case args.size + when 0 + unless (rac[:tasks] || rac[:stop_after_load]) + yield + end + when 1 + rx = args.first + unless rx.kind_of? Regexp + rac.abort_at(ch, "Action: argument has " + + "to be a regular expression.") + end + rac.resolve_hooks << self.new(rac, block, rx) + nil + else + rac.abort_at(ch, "Action: too many arguments.") + end + end + def initialize(rant, block, rx) + @rant = rant + @subdir = @rant.current_subdir + @block = block + @rx = rx + end + def call(target, rel_project_dir) + if target =~ @rx + @rant.resolve_hooks.delete(self) + @rant.goto_project_dir @subdir + @block.call + @rant.resolve(target, rel_project_dir) + end + end + alias [] call + end + end # module Generators +end # module Rant + +Rant::MAIN_OBJECT = self + +class String + alias sub_ext _rant_sub_ext + def to_rant_target + self + end +end + +module Rant::Lib + def parse_caller_elem(elem) + return { :file => "", :ln => 0 } unless elem + if elem =~ /^(.+):(\d+)(?::|$)/ + { :file => $1, :ln => $2.to_i } + else + $stderr.puts "parse_caller_elem: #{elem.inspect}" + { :file => elem, :ln => 0 } + end + + end + module_function :parse_caller_elem +end # module Lib + +module Rant::Console + RANT_PREFIX = "rant: " + ERROR_PREFIX = "[ERROR] " + WARN_PREFIX = "[WARNING] " + def msg_prefix + if defined? @msg_prefix and @msg_prefix + @msg_prefix + else + RANT_PREFIX + end + end + def msg(*text) + pre = msg_prefix + $stderr.puts "#{pre}#{text.join("\n" + ' ' * pre.length)}" + end + def vmsg(importance, *text) + msg(*text) if verbose >= importance + end + def err_msg(*text) + pre = msg_prefix + ERROR_PREFIX + $stderr.puts "#{pre}#{text.join("\n" + ' ' * pre.length)}" + end + def warn_msg(*text) + pre = msg_prefix + WARN_PREFIX + $stderr.puts "#{pre}#{text.join("\n" + ' ' * pre.length)}" + end + def ask_yes_no text + $stderr.print msg_prefix + text + " [y|n] " + case $stdin.readline + when /y|yes/i; true + when /n|no/i; false + else + $stderr.puts(' ' * msg_prefix.length + + "Please answer with `yes' or `no'") + ask_yes_no text + end + end + def prompt text + $stderr.print msg_prefix + text + input = $stdin.readline + input ? input.chomp : input + end + def option_listing opts + rs = "" + opts.each { |lopt, *opt_a| + if opt_a.size == 2 + mode, desc = opt_a + else + sopt, mode, desc = opt_a + end + next unless desc # "private" option + optstr = "" + arg = nil + if mode != GetoptLong::NO_ARGUMENT + if desc =~ /(\b[A-Z_]{2,}\b)/ + arg = $1 + end + end + if lopt + optstr << lopt + if arg + optstr << " " << arg + end + optstr = optstr.ljust(30) + end + if sopt + optstr << " " unless optstr.empty? + optstr << sopt + if arg + optstr << " " << arg + end + end + rs << " #{optstr}\n" + rs << " #{desc.split("\n").join("\n ")}\n" + } + rs + end + extend self +end # module Rant::Console + +module RantContext + include Rant::Generators + + Env = Rant::Env + FileList = Rant::FileList + + def task(targ, &block) + rant.task(targ, &block) + end + + def file(targ, &block) + rant.file(targ, &block) + end + + def enhance(targ, &block) + rant.enhance(targ, &block) + end + + def desc(*args) + rant.desc(*args) + end + + def gen(*args, &block) + rant.gen(*args, &block) + end + + def import(*args, &block) + rant.import(*args, &block) + end + + def plugin(*args, &block) + rant.plugin(*args, &block) + end + + def subdirs(*args) + rant.subdirs(*args) + end + + def source(opt, rantfile = nil) + rant.source(opt, rantfile) + end + + def sys(*args, &block) + rant.sys(*args, &block) + end + + def var(*args, &block) + rant.var(*args, &block) + end + + def make(*args, &block) + rant.make(*args, &block) + end + +end # module RantContext + +class RantAppContext + include RantContext + + def initialize(app) + @__rant__ = app + end + + def rant + @__rant__ + end + + def method_missing(sym, *args) + Rant::MAIN_OBJECT.send(sym, *args) + rescue NoMethodError + raise NameError, "NameError: undefined local " + + "variable or method `#{sym}' for main:Object", caller + end +end + +module Rant + + @__rant__ = nil + class << self + + def run(first_arg=nil, *other_args) + other_args = other_args.flatten + args = first_arg.nil? ? ARGV.dup : ([first_arg] + other_args) + if rant && !rant.run? + rant.run(args.flatten) + else + @__rant__ = Rant::RantApp.new + rant.run(args) + end + end + + def rant + @__rant__ + end + end + +end # module Rant + +class Rant::RantApp + include Rant::Console + + class AutoLoadNodeFactory + def initialize(rant) + @rant = rant + end + def method_missing(sym, *args, &block) + @rant.import "nodes/default" + @rant.node_factory.send(sym, *args, &block) + end + end + + + + OPTIONS = [ + [ "--help", "-h", GetoptLong::NO_ARGUMENT, + "Print this help and exit." ], + [ "--version", "-V", GetoptLong::NO_ARGUMENT, + "Print version of Rant and exit." ], + [ "--verbose", "-v", GetoptLong::NO_ARGUMENT, + "Print more messages to stderr." ], + [ "--quiet", "-q", GetoptLong::NO_ARGUMENT, + "Don't print commands." ], + [ "--err-commands", GetoptLong::NO_ARGUMENT, + "Print failed commands and their exit status." ], + [ "--directory","-C", GetoptLong::REQUIRED_ARGUMENT, + "Run rant in DIRECTORY." ], + [ "--cd-parent","-c", GetoptLong::NO_ARGUMENT, + "Run rant in parent directory with Rantfile." ], + [ "--look-up", "-u", GetoptLong::NO_ARGUMENT, + "Look in parent directories for root Rantfile." ], + [ "--rantfile", "-f", GetoptLong::REQUIRED_ARGUMENT, + "Process RANTFILE instead of standard rantfiles.\n" + + "Multiple files may be specified with this option." ], + [ "--force-run","-a", GetoptLong::REQUIRED_ARGUMENT, + "Force rebuild of TARGET and all dependencies." ], + [ "--dry-run", "-n", GetoptLong::NO_ARGUMENT, + "Print info instead of actually executing actions." ], + [ "--tasks", "-T", GetoptLong::NO_ARGUMENT, + "Show a list of all described tasks and exit." ], + + + [ "--import", "-i", GetoptLong::REQUIRED_ARGUMENT, nil ], + [ "--stop-after-load", GetoptLong::NO_ARGUMENT, nil ], + [ "--trace-abort", GetoptLong::NO_ARGUMENT, nil ], + ] + + ROOT_DIR_ID = "@" + ESCAPE_ID = "\\" + + attr_reader :args + attr_reader :rantfiles + attr_reader :force_targets + attr_reader :plugins + attr_reader :context + alias cx context + attr_reader :tasks + attr_reader :imports + attr_reader :current_subdir + attr_reader :resolve_hooks + attr_reader :rootdir + + attr_accessor :node_factory + + def initialize + @args = [] + @context = RantAppContext.new(self) + @sys = ::Rant::SysObject.new(self) + @rantfiles = [] + @tasks = {} + @opts = { + :verbose => 0, + :quiet => false, + } + @rootdir = Dir.pwd # root directory of project + @arg_rantfiles = [] # rantfiles given in args + @arg_targets = [] # targets given in args + @force_targets = [] # targets given with -a option + @run = false # run method was called at least once + @done = false # run method was successful + @plugins = [] + @var = Rant::RantVar::Space.new + @var.query :ignore, :AutoList, [] + @imports = [] + + @task_desc = nil + @last_build_subdir = "" + + @current_subdir = "" + @resolve_hooks = [] + + @node_factory = AutoLoadNodeFactory.new(self) + end + + def [](opt) + @opts[opt] + end + + def []=(opt, val) + @opts[opt] = val + end + + def expand_path(subdir, path) + case path + when nil; subdir.dup + when ""; subdir.dup + when /^@/; path.sub(/^@/, '') + else + path = path.sub(/^\\(?=@)/, '') + if subdir.empty? + path + else + File.join(subdir, path) + end + end + end + def resolve_root_ref(path) + return File.join(@rootdir, path[1..-1]) if path =~ /^@/ + path.sub(/^\\(?=@)/, '') + end + def project_to_fs_path(path) + sub = expand_path(@current_subdir, path) + sub.empty? ? @rootdir : File.join(@rootdir, sub) + end + def abs_path(subdir, fn) + return fn if Rant::Sys.absolute_path?(fn) + path = File.join(@rootdir, subdir, fn) + path.gsub!(%r{/+}, "/") + path.sub!(%r{/$}, "") if path.length > 1 + path + end + def goto(dir) + goto_project_dir(expand_path(@current_subdir, dir)) + end + def goto_project_dir(dir='') + @current_subdir = dir + abs_path = @current_subdir.empty? ? + @rootdir : File.join(@rootdir, @current_subdir) + unless Dir.pwd == abs_path + Dir.chdir abs_path + vmsg 1, "in #{abs_path}" + end + end + + def run? + @run + end + + def done? + @done + end + + def run(*args) + @run = true + @args.concat(args.flatten) + orig_pwd = @rootdir = Dir.pwd + process_args + Dir.chdir(@rootdir) rescue abort $!.message + load_rantfiles + + raise Rant::RantDoneException if @opts[:stop_after_load] + + @plugins.each { |plugin| plugin.rant_start } + if @opts[:tasks] + show_descriptions + raise Rant::RantDoneException + end + run_tasks + raise Rant::RantDoneException + rescue Rant::RantDoneException + @done = true + @plugins.each { |plugin| plugin.rant_done } + return 0 + rescue Rant::RantAbortException + $stderr.puts "rant aborted!" + return 1 + rescue Exception => e + ch = get_ch_from_backtrace(e.backtrace) + if ch && !@opts[:trace_abort] + err_msg(pos_text(ch[:file], ch[:ln]), e.message) + else + err_msg e.message, e.backtrace[0..4] + end + $stderr.puts "rant aborted!" + return 1 + ensure + Dir.chdir @rootdir if test ?d, @rootdir + hooks = var._get("__at_return__") + hooks.each { |hook| hook.call } if hooks + @plugins.each { |plugin| plugin.rant_plugin_stop } + @plugins.each { |plugin| plugin.rant_quit } + Dir.chdir orig_pwd + end + + + def desc(*args) + if args.empty? || (args.size == 1 && args.first.nil?) + @task_desc = nil + else + @task_desc = args.join("\n") + end + end + + def task(targ, &block) + prepare_task(targ, block) { |name,pre,blk| + @node_factory.new_task(self, name, pre, blk) + } + end + + def file(targ, &block) + prepare_task(targ, block) { |name,pre,blk| + @node_factory.new_file(self, name, pre, blk) + } + end + + def gen(*args, &block) + ch = Rant::Lib::parse_caller_elem(caller[1]) + generator = args.shift + unless generator.respond_to? :rant_gen + abort_at(ch, + "gen: First argument has to be a task-generator.") + end + generator.rant_gen(self, ch, args, &block) + end + + def import(*args, &block) + ch = Rant::Lib::parse_caller_elem(caller[1]) + if block + warn_msg pos_text(ch[:file], ch[:ln]), + "import: ignoring block" + end + args.flatten.each { |arg| + unless String === arg + abort_at(ch, "import: only strings allowed as arguments") + end + unless @imports.include? arg + unless Rant::CODE_IMPORTS.include? arg + begin + vmsg 2, "import #{arg}" + require "rant/import/#{arg}" + rescue LoadError => e + abort_at(ch, "No such import - #{arg}") + end + Rant::CODE_IMPORTS << arg.dup + end + init_msg = "init_import_#{arg.gsub(/[^\w]/, '__')}" + Rant.send init_msg, self if Rant.respond_to? init_msg + @imports << arg.dup + end + } + end + + def plugin(*args, &block) + clr = caller[1] + ch = Rant::Lib::parse_caller_elem(clr) + name = nil + pre = [] + ln = ch[:ln] || 0 + file = ch[:file] + + pl_name = args.shift + pl_name = pl_name.to_str if pl_name.respond_to? :to_str + pl_name = pl_name.to_s if pl_name.is_a? Symbol + unless pl_name.is_a? String + abort(pos_text(file, ln), + "Plugin name has to be a string or symbol.") + end + lc_pl_name = pl_name.downcase + import_name = "plugin/#{lc_pl_name}" + unless Rant::CODE_IMPORTS.include? import_name + begin + require "rant/plugin/#{lc_pl_name}" + Rant::CODE_IMPORTS << import_name + rescue LoadError + abort(pos_text(file, ln), + "no such plugin library -- #{lc_pl_name}") + end + end + pl_class = nil + begin + pl_class = ::Rant::Plugin.const_get(pl_name) + rescue NameError, ArgumentError + abort(pos_text(file, ln), + "no such plugin -- #{pl_name}") + end + + plugin = pl_class.rant_plugin_new(self, ch, *args, &block) + @plugins << plugin + vmsg 2, "Plugin `#{plugin.rant_plugin_name}' registered." + plugin.rant_plugin_init + plugin + end + + def enhance(targ, &block) + prepare_task(targ, block) { |name,pre,blk| + t = resolve(name).last + if t + unless t.respond_to? :enhance + abort("Can't enhance task `#{name}'") + end + t.enhance(pre, &blk) + return t + end + warn_msg "enhance \"#{name}\": no such task", + "Generating a new file task with the given name." + @node_factory.new_file(self, name, pre, blk) + } + end + + def source(opt, rantfile = nil) + unless rantfile + rantfile = opt + opt = nil + end + make_rf = opt != :n && opt != :now + rf, is_new = rantfile_for_path(rantfile) + return false unless is_new + make rantfile if make_rf + unless File.exist? rf.path + abort("source: No such file -- #{rantfile}") + end + + load_file rf + end + + def subdirs(*args) + args.flatten! + ch = Rant::Lib::parse_caller_elem(caller[1]) + args.each { |arg| + if arg.respond_to? :to_str + arg = arg.to_str + else + abort_at(ch, "subdirs: arguments must be strings") + end + loaded = false + prev_subdir = @current_subdir + begin + goto arg + if test(?f, Rant::SUB_RANTFILE) + path = Rant::SUB_RANTFILE + else + path = rantfile_in_dir + end + if path + if defined? @initial_subdir and + @initial_subdir == @current_subdir + rf, is_new = rantfile_for_path(path, false) + @rantfiles.unshift rf if is_new + else + rf, is_new = rantfile_for_path(path) + end + load_file rf if is_new + elsif !@opts[:no_warn_subdir] + warn_msg(pos_text(ch[:file], ch[:ln]), + "subdirs: No Rantfile in subdir `#{arg}'.") + end + ensure + goto_project_dir prev_subdir + end + } + rescue SystemCallError => e + abort_at(ch, "subdirs: " + e.message) + end + + def sys(*args, &block) + args.empty? ? @sys : @sys.sh(*args, &block) + end + + def var(*args, &block) + args.empty? ? @var : @var.query(*args, &block) + end + + def pop_desc + td = @task_desc + @task_desc = nil + td + end + + def abort(*msg) + err_msg(msg) unless msg.empty? + $stderr.puts caller if @opts[:trace_abort] + raise Rant::RantAbortException + end + + def abort_at(ch, *msg) + err_msg(pos_text(ch[:file], ch[:ln]), msg) + $stderr.puts caller if @opts[:trace_abort] + raise Rant::RantAbortException + end + + def show_help + puts "rant [-f Rantfile] [Options] [targets]" + puts + puts "Options are:" + print option_listing(OPTIONS) + end + + def show_descriptions + tlist = select_tasks { |t| t.description } + def_target = target_list.first + if tlist.empty? + puts "rant # => " + list_task_names( + resolve(def_target)).join(', ') + msg "No described tasks." + return + end + prefix = "rant " + infix = " # " + name_length = (tlist.map{ |t| t.to_s.length } << 7).max + cmd_length = prefix.length + name_length + unless tlist.first.to_s == def_target + defaults = list_task_names( + resolve(def_target)).join(', ') + puts "#{prefix}#{' ' * name_length}#{infix}=> #{defaults}" + end + tlist.each { |t| + print(prefix + t.to_s.ljust(name_length) + infix) + dt = t.description.sub(/\s+$/, "") + puts dt.gsub(/\n/, "\n" + ' ' * cmd_length + infix + " ") + } + true + end + + def list_task_names(*tasks) + rsl = [] + tasks.flatten.each { |t| + if t.respond_to?(:has_actions?) && t.has_actions? + rsl << t + elsif t.respond_to? :prerequisites + if t.prerequisites.empty? + rsl << t + else + t.prerequisites.each { |pre| + rsl.concat(list_task_names( + resolve(pre, t.project_subdir))) + } + end + else + rsl << t + end + } + rsl + end + private :list_task_names + + def verbose + @opts[:verbose] + end + + def quiet? + @opts[:quiet] + end + + def pos_text(file, ln) + t = "in file `#{file}'" + t << ", line #{ln}" if ln && ln > 0 + t << ": " + end + + def cmd_msg(cmd) + puts cmd unless quiet? + end + + def cmd_print(text) + print text unless quiet? + $stdout.flush + end + + def cmd_targets + @force_targets + @arg_targets + end + + def running_task(task) + if @current_subdir != @last_build_subdir + cmd_msg "(in #{@current_subdir.empty? ? + @rootdir : @current_subdir})" + @last_build_subdir = @current_subdir + end + if @opts[:dry_run] + task.dry_run + true + end + end + + private + def have_any_task? + !@tasks.empty? + end + + def target_list + if !have_any_task? && @resolve_hooks.empty? + abort("No tasks defined for this rant application!") + end + + target_list = @force_targets + @arg_targets + if target_list.empty? + def_tasks = resolve "default" + unless def_tasks.empty? + target_list << "default" + else + @rantfiles.each { |f| + first = f.tasks.first + if first + target_list << first.reference_name + break + end + } + end + end + target_list + end + + def run_tasks + target_list.each { |target| + if build(target) == 0 + abort("Don't know how to make `#{target}'.") + end + } + end + + def make(target, *args, &block) + ch = nil + if target.respond_to? :to_hash + targ = target.to_hash + ch = Rant::Lib.parse_caller_elem(caller[1]) + abort_at(ch, "make: too many arguments") unless args.empty? + tn = nil + prepare_task(targ, block, ch) { |name,pre,blk| + tn = name + @node_factory.new_file(self, name, pre, blk) + } + build(tn) + elsif target.respond_to? :to_rant_target + rt = target.to_rant_target + opt = args.shift + unless args.empty? + ch ||= Rant::Lib.parse_caller_elem(caller[1]) + abort_at(ch, "make: too many arguments") + end + if block + ch ||= Rant::Lib.parse_caller_elem(caller[1]) + prepare_task(rt, block, ch) { |name,pre,blk| + @node_factory.new_file(self, name, pre, blk) + } + build(rt) + else + build(rt, opt||{}) + end + elsif target.respond_to? :rant_gen + ch = Rant::Lib.parse_caller_elem(caller[1]) + rv = target.rant_gen(self, ch, args, &block) + unless rv.respond_to? :to_rant_target + abort_at(ch, "make: invalid generator return value") + end + build(rv.to_rant_target) + rv + else + ch = Rant::Lib.parse_caller_elem(caller[1]) + abort_at(ch, + "make: generator or target as first argument required.") + end + end + public :make + + def build(target, opt = {}) + opt[:force] = true if @force_targets.delete(target) + opt[:dry_run] = @opts[:dry_run] + matching_tasks = 0 + old_subdir = @current_subdir + old_pwd = Dir.pwd + resolve(target).each { |t| + unless opt[:type] == :file && !t.file_target? + matching_tasks += 1 + begin + t.invoke(opt) + rescue Rant::TaskFail => e + err_task_fail(e) + abort + end + end + } + @current_subdir = old_subdir + Dir.chdir old_pwd + matching_tasks + end + public :build + + def resolve(task_name, rel_project_dir = @current_subdir) + s = @tasks[expand_path(rel_project_dir, task_name)] + case s + when nil + @resolve_hooks.each { |s| + s = s[task_name, rel_project_dir] + return s if s + } + [] + when Rant::Node; [s] + else # assuming list of tasks + s + end + end + public :resolve + + def rec_save_resolve(task_name, excl_hook, rel_project_dir = @current_subdir) + s = @tasks[expand_path(rel_project_dir, task_name)] + case s + when nil + @resolve_hooks.each { |s| + next if s == excl_hook + s = s[task_name, rel_project_dir] + return s if s + } + [] + when Rant::Node; [s] + else + s + end + end + public :rec_save_resolve + + def at_resolve(&block) + @resolve_hooks << block if block + end + public :at_resolve + + def at_return(&block) + hooks = var._get("__at_return__") + if hooks + hooks << block + else + var._set("__at_return__", [block]) + end + end + public :at_return + + def select_tasks + selection = [] + @rantfiles.each { |rf| + rf.tasks.each { |t| + selection << t if yield t + } + } + selection + end + public :select_tasks + + def load_rantfiles + unless @arg_rantfiles.empty? + @arg_rantfiles.each { |fn| + if test(?f, fn) + rf, is_new = rantfile_for_path(fn) + load_file rf if is_new + else + abort "No such file -- #{fn}" + end + } + return + end + return if have_any_task? + fn = rantfile_in_dir + if @opts[:cd_parent] + old_root = @rootdir + until fn or @rootdir == "/" + @rootdir = File.dirname(@rootdir) + fn = rantfile_in_dir(@rootdir) + end + if @rootdir != old_root and fn + Dir.chdir @rootdir + cmd_msg "(in #@rootdir)" + end + end + if fn + rf, is_new = rantfile_for_path(fn) + load_file rf if is_new + return + end + have_sub_rantfile = test(?f, Rant::SUB_RANTFILE) + if have_sub_rantfile || @opts[:look_up] + cur_dir = Dir.pwd + until cur_dir == "/" + cur_dir = File.dirname(cur_dir) + Dir.chdir cur_dir + fn = rantfile_in_dir + if fn + @initial_subdir = @rootdir.sub( + /^#{Regexp.escape cur_dir}\//, '') + @rootdir = cur_dir + cmd_msg "(root is #@rootdir, in #@initial_subdir)" + @last_build_subdir = @initial_subdir + rf, is_new = rantfile_for_path(fn) + load_file rf if is_new + goto_project_dir @initial_subdir + if have_sub_rantfile + rf, is_new = rantfile_for_path( + Rant::SUB_RANTFILE, false) + if is_new + @rantfiles.unshift rf + load_file rf + end + end + break + end + end + end + if @rantfiles.empty? + abort("No Rantfile found, looking for:", + Rant::RANTFILES.join(", ")) + end + end + + def load_file(rantfile) + vmsg 1, "source #{rantfile}" + @context.instance_eval(File.read(rantfile), rantfile) + end + private :load_file + + def rantfile_in_dir(dir=nil) + ::Rant::RANTFILES.each { |rfn| + path = dir ? File.join(dir, rfn) : rfn + return path if test ?f, path + } + nil + end + + def process_args + old_argv = ARGV.dup + ARGV.replace(@args.dup) + cmd_opts = GetoptLong.new(*OPTIONS.collect { |lst| lst[0..-2] }) + cmd_opts.quiet = true + cmd_opts.each { |opt, value| + case opt + when "--verbose"; @opts[:verbose] += 1 + when "--version" + puts "rant #{Rant::VERSION}" + raise Rant::RantDoneException + when "--help" + show_help + raise Rant::RantDoneException + when "--directory" + @rootdir = File.expand_path(value) + when "--rantfile" + @arg_rantfiles << value + when "--force-run" + @force_targets << value + when "--import" + import value + else + @opts[opt.sub(/^--/, '').tr('-', "_").to_sym] = true + end + } + rescue GetoptLong::Error => e + abort(e.message) + ensure + rem_args = ARGV.dup + ARGV.replace(old_argv) + rem_args.each { |ra| + if ra =~ /(^[^=]+)=([^=]+)$/ + vmsg 2, "var: #$1=#$2" + @var[$1] = $2 + else + @arg_targets << ra + end + } + end + + def prepare_task(targ, block, clr = caller[2]) + + if targ.is_a? Hash + targ.reject! { |k, v| clr = v if k == :__caller__ } + end + ch = Hash === clr ? clr : Rant::Lib::parse_caller_elem(clr) + + name, pre = normalize_task_arg(targ, ch) + + file, is_new = rantfile_for_path(ch[:file]) + nt = yield(name, pre, block) + nt.rantfile = file + nt.project_subdir = @current_subdir + nt.line_number = ch[:ln] + nt.description = @task_desc + @task_desc = nil + file.tasks << nt + hash_task nt + nt + end + public :prepare_task + + def hash_task(task) + n = task.full_name + et = @tasks[n] + case et + when nil + @tasks[n] = task + when Rant::Node + mt = [et, task] + @tasks[n] = mt + else # assuming list of tasks + et << task + end + end + + def normalize_task_arg(targ, ch) + name = nil + pre = [] + + if targ.is_a? Hash + if targ.empty? + abort_at(ch, "Empty hash as task argument, " + + "task name required.") + end + if targ.size > 1 + abort_at(ch, "Too many hash elements, " + + "should only be one.") + end + targ.each_pair { |k,v| + name = normalize_task_name(k, ch) + pre = v + } + unless ::Rant::FileList === pre + if pre.respond_to? :to_ary + pre = pre.to_ary.dup + pre.map! { |elem| + normalize_task_name(elem, ch) + } + else + pre = [normalize_task_name(pre, ch)] + end + end + else + name = normalize_task_name(targ, ch) + end + + [name, pre] + end + public :normalize_task_arg + + def normalize_task_name(arg, ch) + return arg if arg.is_a? String + if Symbol === arg + arg.to_s + elsif arg.respond_to? :to_str + arg.to_str + else + abort_at(ch, "Task name has to be a string or symbol.") + end + end + + def rantfile_for_path(path, register=true) + abs_path = File.expand_path(path) + file = @rantfiles.find { |rf| rf.path == abs_path } + if file + [file, false] + else + file = Rant::Rantfile.new abs_path + file.project_subdir = @current_subdir + @rantfiles << file if register + [file, true] + end + end + + def get_ch_from_backtrace(backtrace) + backtrace.each { |clr| + ch = ::Rant::Lib.parse_caller_elem(clr) + if ::Rant::Env.on_windows? + return ch if @rantfiles.any? { |rf| + rf.path.tr("\\", "/").sub(/^\w\:/, '') == + ch[:file].tr("\\", "/").sub(/^\w\:/, '') + } + else + return ch if @rantfiles.any? { |rf| + rf.path == ch[:file] + } + end + } + nil + end + + def err_task_fail(e) + msg = [] + t_msg = ["Task `#{e.tname}' fail."] + orig = e + loop { orig = orig.orig; break unless Rant::TaskFail === orig } + if orig && orig != e && !(Rant::RantAbortException === orig) + ch = get_ch_from_backtrace(orig.backtrace) + msg << pos_text(ch[:file], ch[:ln]) if ch + unless Rant::CommandError === orig && !@opts[:err_commands] + msg << orig.message + msg << orig.backtrace[0..4] unless ch + end + end + if e.msg && !e.msg.empty? + ch = get_ch_from_backtrace(e.backtrace) + t_msg.unshift(e.msg) + t_msg.unshift(pos_text(ch[:file], ch[:ln])) if ch + end + err_msg msg unless msg.empty? + err_msg t_msg + end +end # class Rant::RantApp + +$".concat(['rant/rantlib.rb', 'rant/init.rb', 'rant/rantvar.rb', 'rant/rantsys.rb', 'rant/import/filelist/core.rb', 'rant/node.rb', 'rant/import/nodes/default.rb', 'rant/coregen.rb']) +Rant::CODE_IMPORTS.concat %w(nodes/default + ) + +# Catch a `require "rant"', sad... +alias require_backup_by_rant require +def require libf + if libf == "rant" + # TODO: needs rework! look at lib/rant.rb + self.class.instance_eval { include Rant } + else + begin + require_backup_by_rant libf + rescue + raise $!, caller + end + end +end + +exit Rant.run --- rant-0.5.8.orig/debian/doc/examples/debian_package/pkgrc.rb +++ rant-0.5.8/debian/doc/examples/debian_package/pkgrc.rb @@ -0,0 +1,238 @@ +#!/usr/bin/env ruby +raise 'Please, use ruby1.8.4 or later.' if RUBY_VERSION < '1.8.4' +=begin + + Rantfile example for making a simple debian package of a ruby program + using git-buildpackage with debuild + + Copyright (C) 2007 Ralph Amissah + + * License: LGPL - GNU Lesser General Public License + [same license as Rant provided within the Rant package] + + * Ralph Amissah + Ralph Amissah + + Rant is a Ruby 'ant' by Stefan Lang + * Rant may be downloaded and installed from: + http://make.rubyforge.org/ + + Notes on use: + + This Rantfile is used in conjunction with the pkg.yml example provided + (example is easily extended and works for package rant, and package diakonos) + + * package should be in directory with package name without package version + number + * Rantfile and pkg.yml should be in directory above package directory, + e.g. for rant ls + Rantfile, pkg.yml rant/ + + * provide details of package in pkg.yml file [which is a yaml file] (see + example provided) + + * once these two files are in place for help on package and on possible + actions, enter: + rant + rant info + rant -T + + * NOTE to create independent rant independent ruby script: + rant-import --auto [provide name of ruby (rant exported) script] + +=end +#% produce a makefile suitable for the target platform +#require 'mkmf' +#create_makefile("sisu") +module RC + require 'date' + require 'find' + require 'fileutils' + require 'rbconfig.rb' + #require 'yaml' + include FileUtils::Verbose + class Package + attr_reader :name,:aka,:name_up,:name_deb,:summary,:author,:author_email,:homepage,:maintainer,:maintainer_email,:version_base,:version_project,:version_deb,:version_deb_patch,:git_up,:git_deb,:reprepro_path,:reprepro_branch,:remote_host,:remote_user,:remote_archive,:remote_apt_archive,:gpg_mount,:ymd,:week_slash_day,:sys_arch,:sys_arch_site,:dir_bin,:dir_lib,:dir_data,:dir_conf,:dir_man,:dir_output,:rubylib,:pwd + def initialize + @pkg={} + @dv='-' + @home,@pwd,@user=ENV['HOME'],ENV['PWD'],ENV['USER'] + @git_up='upstream' + @git_deb='master' + @gpg_mount=nil + yml=false + path_up=@pwd.gsub(/\/[^\/]+$/,'') + rc_yml_path=[@pwd,path_up] + rc_yml=['pkgrc','package','pkg'] + rc_yml_path.each do |pkgrc_path| + rc_yml.each do |pkgrc| + pkg="#{pkgrc_path}/#{pkgrc}.yml" + if FileTest.exist?(pkg) + unless @rc + require 'yaml' + @rc ||= YAML::load(File::open(pkg)) + yml=true + break + end + end + end + end + @today=Date.today.to_s + @time=Time.now + day=if @time.day.to_s =~/^(\d)$/; "0#{$1}" + else @time.day.to_s + end + month=if @time.month.to_s =~/^(\d)$/; "0#{$1}" + else @time.month.to_s + end + @ymd="#{@time.year}-#{month}-#{day}" + @w=@time.strftime("%W") + @weekonly=@w + @week="#{@time.year}w#@w" + @monthonly=month + @month="#{@time.year}#{@time.month}" + @year=@time.year + d=@time.wday + @week_stamp="#{@time.year}w#@w" + @week_slash_day="#@week_stamp/#{d}" + @week_dash_day="#@week_stamp-#{d}" + #%% system configuration + @host=Config::CONFIG['host'] + @sys_arch=Config::CONFIG['archdir'] + @sys_arch_site=Config::CONFIG['sitearchdir'] + @dir_bin=Config::CONFIG['bindir'] + @dir_lib=Config::CONFIG['sitelibdir'] + @dir_data=Config::CONFIG['datadir'] + @dir_conf=Config::CONFIG['sysconfdir'] #etc + @dir_man=Config::CONFIG['mandir'] + @dir_output="#{Config::CONFIG['localstatedir']}/#{@pkg[:pn]}" + @rubylib=Config::CONFIG['LIBRUBYARG_SHARED'] + @pwd=Dir.pwd + if yml + if defined? @rc['package']['name'] + @name=@rc['package']['name'] + else puts 'pkg.yml does not provide package name as required [package:name:]' + exit + end + if defined? @rc['package']['version'] + @version_project=@rc['package']['version'] + else puts 'pkg.yml does not provide upstream package version number as required [package:version:]' + exit + end + @summary=if defined? @rc['package']['summary'] + @rc['package']['summary'] + else '' + end + @author=if defined? @rc['package']['author'] + @rc['package']['author'] + else '' + end + @author_email=if defined? @rc['package']['email'] + @rc['package']['email'] + else '' + end + @homepage=if defined? @rc['package']['homepage'] + @rc['package']['homepage'] + else '' + end + if defined? @rc['package']['debian_patch'] + @version_deb_patch=@rc['package']['debian_patch'] + else puts 'pkg.yml does not provide debian patch level as required [package:debian_patch:]' + exit + end + if defined? @rc['package']['alias'] + @aka=@rc['package']['alias'] + end + if defined? @rc['git_build_package']['upstream'] + @git_up=@rc['git_build_package']['upstream'] + end + if defined? @rc['git_build_package']['debian'] + @git_deb=@rc['git_build_package']['debian'] + end + if defined? @rc['reprepro']['path'] + @reprepro_path=@rc['reprepro']['path'] + @reprepro_branch=if defined? @rc['reprepro']['branch'] + @rc['reprepro']['branch'] + else puts 'please provide debian branch for reprepro, using unstable' + 'unstable' + end + end + if defined? @rc['remote']['host'] + @remote_host=@rc['remote']['host'] + @remote_user=if defined? @rc['remote']['user'] + @rc['remote']['user'] + else puts 'using current user as default user' + `whoami` + end + if defined? @rc['remote']['archive'] + @remote_archive=@rc['remote']['archive'] + else puts 'information on the directory path in the remote archive has not been provided' + end + @remote_user_and_host="#{@remote_user}@#{remote_host}" + @remote_apt_archive="#@remote_user_and_host:#{@remote_archive}" + end + if defined? @rc['gpg']['mount'] + @gpg_mount="mount #{@rc['gpg']['mount']}" + else '' + end + @aka ||=@name + @name_up="#@name-#@version_project" + @name_deb="#@name_up-#@version_deb_patch" + @version_deb="#@version_project-#@version_deb_patch" + @version_base=/(\d+\.\d+)\.\d+/.match(@version_project)[1] + elsif FileTest.exist?("#@pwd/version") + project=`cat version`.strip #--> sisu-0.48.9-1 + @name_up,@name,@version_up,@version_base,deb_ver=/((.+?)-((\d+\.\d+)\.\d+))-(\d+)/.match(project)[1..5] + @name_deb=project + @version_deb=@version_project + '-' + deb_ver + end + x='' + @maintainer=if defined? @rc['maintainer']['name'] + @maintainer=@rc['maintainer']['name'] + else + name=[ENV['GIT_AUTHOR_NAME'],ENV['GIT_COMMITTER_NAME']] + name.each do |n| + x=n if n=~/\S+/ + break if n=~/\S+/ + end + if x=~/\S+/; @maintainer=x + else puts "please maintainer's name in pkg.yaml or provide shell rc file with GIT_AUTHOR_NAME or GIT_COMMITTER_NAME" + end + end + x='' + if defined? @rc['maintainer']['email'] + @maintainer_email=@rc['maintainer']['email'] + else + email=[ENV['GIT_AUTHOR_EMAIL'],ENV['GIT_COMMITTER_EMAIL']] + email.each do |n| + x=n if n=~/\S+/ + break if n=~/@/ + end + if x=~/\S+/; @maintainer_email=x + else puts "please maintainer's email in pkg.yaml or provide shell rc file with GIT_AUTHOR_EMAIL or GIT_COMMITTER_EMAIL" + end + end + end + def pkg_info + aka="\n :aka - pkg alias: #{@aka}" if @aka != @name + puts < + Ralph Amissah + + Rant is a Ruby 'ant' by Stefan Lang + * Rant may be downloaded and installed from: + http://make.rubyforge.org/ + + Notes on use: + + This Rantfile is used in conjunction with the rantrc.yml example provided + (example is easily extended and works for package rant, and package diakonos) + + * package should be in directory with package name without package version + number + * Rantfile and rantrc.yml should be in directory above package directory, + e.g. for rant ls + Rantfile, rantrc.yml rant/ + + * provide details of package in rantrc.yml file [which is a yaml file] (see + example provided) + + * once these two files are in place for help on package and on possible + actions, enter: + rant + rant info + rant -T + + * NOTE to create independent rant independent ruby script: + rant-import --auto [provide name of ruby (rant exported) script] + +=end +#%% produce a makefile suitable for the target platform +#require 'mkmf' +#create_makefile("sisu") +require 'pkgrc' +include RC +@pkg=RC::Package.new +p @pkg.pwd +@rant_desc="Rantfile for debian git-buildpackage of: #{@pkg.aka}" +u=`whoami` +i=`id` +if u =~/root/ or i =~/root/ or i=~/(?:uid|gid|groups)=0[^\d]/ + puts "This build program is NOT to be run as root.\n\n" + exit +end +def pkg_info + @pkg.pkg_info +end +def home_750 + system("chmod 750 #@home") +end +def home_755 + system("chmod 755 #@home") +end +def mv_dir_pkg_to_pkg_and_version #not used + if File.directory?(@pkg.name) + system(%{ + mv #{@pkg.name} #{@pkg.name_up} + }) + else exit + end +end +def mv_dir_pkg_and_version_to_pkg #not used + if File.directory?(@pkg.name_up) + system(%{ + mv #{@pkg.name_up} #{@pkg.name} + }) + else exit + end +end +def answer?(ask) + response='redo' + print ask + " ['yes', 'no' or 'quit']: " + response=File.new('/dev/tty').gets.strip + #response=gets.strip + ans=if response == 'yes'; true + elsif response == 'no'; false + elsif response =~/^quit|exit$/; exit + else puts "[please type: 'yes', 'no' or 'quit']" + answer?(ask) + end + ans +end +def signed? + response=answer?(%{create a signed debian package?: yes [or no for unsigned]: }) + puts '---' + @sign=if response + #system(@gpg[:mount]) if @gpg[:mount] and not @gpg[:mount].empty? + #puts response + true + else false + end +end +def cd_umount + system('umount /cdrom') + puts 'unmount sd - PLEASE REMOVE CD-ROM' +end +def git_co_upstream + system(%{ + cd #{@pkg.name} + echo "git-checkout #{@pkg.git_up}" + git-checkout #{@pkg.git_up} + }) +end +def git_co_debian + system(%{ + cd #{@pkg.name} + echo "git-checkout #{@pkg.git_deb}" + git-checkout #{@pkg.git_deb} + }) +end +def git_commit(commit_message) + system(%{ + cd #{@pkg.name} + git-commit -a -m"#{commit_message}" + }) +end +def git_merge_upstream + git_co_debian + system(%{ + cd #{@pkg.name} + git-diff upstream + git-status + }) + response=answer?(%{merge upstream?: yes or no to skip: }) + puts "--- #{response} ---" + if response + system(%{ + cd #{@pkg.name} + git-merge upstream + }) + end +end +def gitignore +ignore=< #{@pkg.name}/.git/info/exclude + }) +end +def clean_waste + system(%{ + rm -v */**/*.sw? + rm -v */**/.*.sw? + rm -v */**/*~ + }) +end +def default_notice #package_reminder + response='' + while response !~/^[yn]$/ + print %{#{@rant_desc} + Information on alternative actions is available using: + "rant help" or "rant -T" + Default action selected - "debianise #{@pkg.name_up}" (using git-buildpackage) proceed? [y/n]: } + response="y\n" #response=File.new('/dev/tty').gets.strip + exit if response =~/^(n|quit)$/ + end + if response =~/^n$/ + while response !~/^[yn]$/ + print %{do you wish to edit CHANGELOG (& README) now? to edit [y], to abandon package-build [n]: } + exit if response =~/^(n|quit)$/ + end + system(" vim #{@pkg.name}/{CHANGELOG,README} ") if response.include? ?y + end +end +def dch + p @pkg.version_deb + @dch=if @pkg.version_deb; "debchange -v #{@pkg.version_deb}" + else 'debchange -a' + end + #@dch='debchange -i' +end +def dch_news(news=false) + @dch_news=if news; 'debchange --news' + else '' + end + #@dch='debchange -i' +end +def dchi + p @pkg.version_deb + @dch=if @pkg.version_deb; "debchange -v #{@pkg.version_deb}" + else 'debchange -i' + end +end +def pkg_git #% everything happens here + if File.directory?(@pkg.name) + buildpackage=if @sign; %{git-buildpackage -D -i\.git -I.git --git-upstream-branch="#{@pkg.git_up}" --git-debian-branch="#{@pkg.git_deb}" --git-tag} #build package, signed check dependencies + else %{git-buildpackage -us -uc -D --git-upstream-branch="#{@pkg.git_up}" --git-debian-branch="#{@pkg.git_deb}"} #build package, no signing check dependencies + end + gitignore + system(%{ + cd #{@pkg.name} + git-checkout #{@pkg.git_deb} + rm -v **/\.* #does not remove .git which is a directory [edit out, not everyone will want this] [zsh specific not bash] + #@dch #update debian version number + git add . && git commit -a -m "Updated #{@pkg.name_up}" #version changes + #{buildpackage} + debuild clean + cd - + }) + echo_build_output + else puts "directory NOT FOUND: #{@pkg.name}" + end +end +def echo_build_output + system(%{ + #ls -hoS #{@pkg.name}*#{@pkg.version_deb}*.deb + echo 'source ---' + ls -sh1 #{@pkg.name}*#{@pkg.version_deb}*.dsc #{@pkg.name}*#{@pkg.version_project}*.tar.gz #{@pkg.name}*#{@pkg.version_deb}*.diff.gz + echo 'deb ---' + ls -shS1 #{@pkg.name}*#{@pkg.version_deb}*.deb + }) +end +def git_checkpoint #not used + unless @tag =~/^quit$/i + puts %{git tag --patch-name="#{@week_slash_day} #@tag" --checkpoint\n} + system(%{ + cd #{@pkg.name} + git tag --patch-name="#{@week_slash_day} #@tag" --checkpoint + cd - + }) + end +end +def changes + changes=`cat #{@pkg.name}*.changes` + p changes + changes +end +def debian_files #in case you need it, should be automatically handled by dch ... remove + pwd=Dir.pwd + system(%{echo "#{@pkg.name}_#{@pkg.version_project}_all.deb text extra +#{@pkg.name}-examples_#{@pkg.version_project}_all.deb text extra" > #{pwd}/#{@pkg.name}-#{@pkg.version_project}/debian/files +}) +end +def reprepro + changes=`ls #{@pkg.name}_#{@pkg.version_deb}*.changes` + unless changes.nil? or changes.empty? + system(%{reprepro -Vb #{@pkg.reprepro_path} include #{@pkg.reprepro_branch} #{changes}}) + end +end +def dpkg_install + echo_build_output + system(" + #sudo dpkg -i `echo #{@pkg.name}*#{@pkg.version_deb}*.deb` + ") +end +def remote_host + system(%{ + rsync -av --delete-after #{@pkg.reprepro_path}/{dists,pool} #{@pkg.remote_apt_archive}/. + }) +end +def pwd + puts 'ruby: ' + Dir.pwd + system(%{echo "zsh: $PWD"}) +end +def deb_dir_skel + def control +<= 5) +Standards-Version: 3.7.2 + +Package: #{@pkg.name} +Architecture: all +Depends: ruby (>= 1.8.2) +Description: [---] + [---] + . + Homepage: +WOK + end + def rules +< +on Mon, 2 May 2005 17:33:58 +0100. + +The homepage is: + + +The original source can always be found at: + + + +Copyright (C) 1997, 1998, 1999, 2000, 20001, 2002, 2003, 2004, 2005 +Ralph Amissah + +License: GPL 2 or later + + GPL2 summary: + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this package; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301, USA + + If you have Internet connection, the latest version of the GPL should be + available from these locations: + + + + + On Debian systems, the complete text of the GNU General + Public License can be found in `/usr/share/common-licenses/GPL'. + + The Free Software Foundation: + +WOK + end + def install + bin=if File.directory?("#{@pkg.pwd}/#{@pkg.name}/bin") + "bin/ usr\n" + else '' + end + lib=if File.directory?("#{@pkg.pwd}/#{@pkg.name}/lib") + if File.directory?("#{@pkg.pwd}/#{@pkg.name}/lib/#{@pkg.name}") + "lib/#{@pkg.name} usr/lib/ruby/1.8\n" + else + end + else '' + end + conf=if File.directory?("#{@pkg.pwd}/#{@pkg.name}/conf/#{@pkg.name}") + "conf/#{@pkg.name} etc\n" + else '' + end + if File.directory?("#{@pkg.pwd}/#{@pkg.name}/data") + if File.directory?("#{@pkg.pwd}/#{@pkg.name}/data/#{@pkg.name}") or File.directory?("#{@pkg.pwd}/#{@pkg.name}/data/doc") + share=if File.directory?("#{@pkg.pwd}/#{@pkg.name}/data/#{@pkg.name}") + "data/#{@pkg.name} usr/share\n" + else '' + end + doc=if File.directory?("#{@pkg.pwd}/#{@pkg.name}/data/doc/#{@pkg.name}") + "data/doc/#{@pkg.name} usr/share/doc\n" + elsif File.directory?("#{@pkg.pwd}/#{@pkg.name}/data/doc") + "data/doc/ usr/share/doc/#{@pkg.name}\n" + else '' + end + else + end + elsif File.directory?("#{@pkg.pwd}/#{@pkg.name}/share") + if File.directory?("#{@pkg.pwd}/#{@pkg.name}/share/#{@pkg.name}") or File.directory?("#{@pkg.pwd}/#{@pkg.name}/share/doc") + share=if File.directory?("#{@pkg.pwd}/#{@pkg.name}/share/#{@pkg.name}") + "share/#{@pkg.name} usr/share\n" + elsif File.directory?("#{@pkg.pwd}/#{@pkg.name}/share/doc") + "data/doc/ usr/share/doc/#{@pkg.name}\n" + else '' + end + doc=if File.directory?("#{@pkg.pwd}/#{@pkg.name}/share/doc/#{@pkg.name}") + "share/doc/#{@pkg.name} usr/share/doc\n" + elsif File.directory?("#{@pkg.pwd}/#{@pkg.name}/share/doc") + "data/doc/ usr/share/doc/#{@pkg.name}\n" + else '' + end + else + end + elsif File.directory?("#{@pkg.pwd}/#{@pkg.name}/doc") + doc=if File.directory?("#{@pkg.pwd}/#{@pkg.name}/doc/#{@pkg.name}") + "doc/#{@pkg.name} usr/share/doc\n" + #"doc/ usr/share/doc/#{@pkg.name}" + else "doc usr/share/doc/#{@pkg.name}\n" + end + else '' + end + "#{bin}#{lib}#{conf}#{share}#{doc}" + end + def manpages + man_1=if File.exist?("#{@pkg.pwd}/#{@pkg.name}/man/man1/#{@pkg.name}.1") + "man/man1/#{@pkg.name}.1\n" + else '' + end + man_7=if File.exist?("#{@pkg.pwd}/#{@pkg.name}/man/man7/#{@pkg.name}.7") + "man/man7/#{@pkg.name}.7\n" + else '' + end + man_8=if File.exist?("#{@pkg.pwd}/#{@pkg.name}/man/man8/#{@pkg.name}.8") + "man/man8/#{@pkg.name}.8\n" + else '' + end + "#{man_1}#{man_7}#{man_8}" + end + def readme_debian #README.Debian + end + def changelog +< [:help] +desc "info on package" +task :info => [:info] +task :i => [:info] +desc "help for Rantfile to make debian package (using git-buildpackage) & apt archive" +task :h => [:help] +task :w => [:what] +task :what => [:what] +desc "project description" +task :which => [:what] +task :dbp => [:pkg] +task :package => [:pkg_git] +desc "git build package - make debian package" +task :pkg => :pkg_git +task :pkg_git => [:pre_pkg_git,:dch,:package_git,:post_pkg] +desc "git build package and add NEWS file - make debian package" +task :pkg_news => [:pre_pkg_git,:dch_news,:package_git,:post_pkg] +desc "bump sisu version from pkgrc.yml" +desc "man 2 html" +task :man2html => [:man_html] +desc "copy apt repo online" +task :remote_host => [:remote_host] +desc "install resulting debs if any, dpkg -i `echo *[version-number]*.deb`" +task :dpkgi => [:dpkg_install] +desc "bump up @pkg.name version" +desc "checkpoint git repository" +task :checkpoint => [:git_checkpoint] +desc "dgst info" +task :dgst => [:changes] +desc "make tarball" +task :tgz => [:tgz_mk] +desc "update apt-archive using reprepro" +task :reprepro => [:reprepro] +desc "system info" +task :system_info => [:system_info] +desc "initialise skeleton debian directory for a typical simple ruby application" +task :deb_dir_init => [:deb_dir_init] +desc "system parameters seen by ruby" +task :system_param => [:system_param] +task :pwd => [:pwd] +desc "create new ruby executable version of Rantfile deb_rb_pkg_[name]" +task :rant_to_ruby => [:rant_to_ruby] +desc "rdoc" +task :rdoc => [:rdoc] +# #%% dars / depackage / git-buildpackage tasks +task :info do + pkg_info +end +task :package_notices do + default_notice +end +task :man_html do + man2html +end +task :dch do + dch + dch_news(false) +end +task :dch_news do + dch + dch_news(true) +end +task :dchi do + dchi +end +#task :package do +# pkg_git +#end +task :package_git do + pkg_git +end +#task :cleanup do +# clean +#end +task :changes do + changes +end +task :reprepro do + reprepro +end +task :remote_host do + remote_host +end +task :remote_host_exp do + remote_host_experimental_package +end +task :pre_pkg_generic do + home_755 + signed? + update_sisu_rant_installer +end +task :pre_pkg_git do + home_755 + puts " will checkout upstream, update and commit CHANGELOG and version files; + will checkout debian directory, attempt to merge upstream, and then; + will attempt to build package;\n + if you have not already done so, you may *now* wish to: + * update package the version in the pkg.yml file + * edit the CHANGELOG (& README)\n\n" + #mv_dir_pkg_to_pkg_and_version + signed? + git_co_upstream + git_commit('changelog and version updated') + git_co_debian + git_merge_upstream +end +task :post_pkg do + cd_umount + home_750 + #mv_dir_pkg_and_version_to_pkg +end +task :dpkg_install do + dpkg_install +end +task :pwd do + pwd +end +task :system_info do + rant_system_info +end +task :system_param do + Config::CONFIG.each {|c| p c } +end +task :deb_dir_init do + deb_dir_init +end +task :rant_to_ruby do + rant_to_ruby +end +task :rdoc do + rdoc +end +task :help do + rant_help +end +__END__