Index: ChangeLog from Nicolas Pouillard ertai@lrde.epita.fr
* vcs: Remove the ruby_ex external link, use the gem package instead. * vcs/Rakefile: Use the core_ex common rakefile. * vcs/SPEC.yml: New. Package meta data. * vcs/SPEC.dyn.yml: New. Package generated meta data. * vcs/AUTHORS: New. * vcs/NEWS: New. * vcs/src: Rename to ... * vcs/lib/vcs: ... this. * vcs/lib/vcs/ask.rb: Remove, because ask is present in ruby_ex. * vcs/lib/vcs/edit.rb: New. * vcs/bin/vcs: Update requires, load_path, version, and some environement variables definition.
AUTHORS | 6 + NEWS | 3 Rakefile | 79 +-------------- SPEC.dyn.yml | 9 + SPEC.yml | 35 +++++++ bin/vcs | 27 ++--- lib/vcs/diffstat.rb | 2 lib/vcs/edit.rb | 15 +++ lib/vcs/vcs.rb | 65 ++++++------- src/ask.rb | 101 -------------------- src/changelog.rb | 115 ----------------------- src/conflict.rb | 21 ---- src/cvs.rb | 21 ---- src/diff.rb | 18 --- src/diffstat.rb | 30 ------ src/last_changed_date.rb | 16 --- src/mail.rb | 51 ---------- src/message.rb | 69 ------------- src/mycommit.rb | 86 ----------------- src/news.rb | 118 ----------------------- src/prcs.rb | 21 ---- src/revision.rb | 18 --- src/status.rb | 17 --- src/svn.rb | 29 ----- src/tools.rb | 22 ---- src/vcs.rb | 234 ----------------------------------------------- 26 files changed, 119 insertions(+), 1109 deletions(-)
Index: vcs/lib/vcs/diffstat.rb --- vcs/lib/vcs/diffstat.rb (revision 206) +++ vcs/lib/vcs/diffstat.rb (working copy) @@ -14,7 +14,7 @@ check_diffstat data_diff = diff(*a) cmd = @@diffstat < data_diff.output.open > [@out_path, @err_path] - cmd.sys + cmd.run(@runner) end alias_command :ds, :diffstat
Index: vcs/bin/vcs --- vcs/bin/vcs (revision 206) +++ vcs/bin/vcs (working copy) @@ -16,18 +16,11 @@ require 'optparse' require 'set'
-begin - REV="$Rev$".sub(/LastChangedRevision:\s+/, '').to_i -rescue - REV=-1 -end - +VCS_VERSION = '0.2.148' VCS_PATH = Pathname.new(__FILE__).expand_path VCS_DIR, VCS = VCS_PATH.split -SRC = VCS_DIR + '..' + 'src' -RUBY_EX = VCS_DIR + '..' + 'ruby_ex' -$: << SRC.to_s -$: << RUBY_EX.to_s +LIB = VCS_DIR + '..' + 'lib' +$: << LIB.to_s
dir = Pathname.pwd while not dir.root? and not (vcs_dir = dir + 'vcs').exist? @@ -46,14 +39,14 @@ "#{VCS}: #{progname}#{severity.downcase}: #{msg}\n" end
-Pathname.glob("{#{SRC}/**,#{vcs_dir}}/*.rb") do |file| +Pathname.glob("{#{LIB}/**,#{vcs_dir}}/*.rb") do |file| LOG.debug { file.basename.to_s } begin - require file.basename.to_s - rescue LoadError => ex + require "vcs/#{file.basename}" + rescue LoadError begin require file.to_s - rescue + rescue LoadError => ex raise ex end end @@ -115,7 +108,7 @@ end
opts.on_tail('--version', 'Show version') do - STDOUT.puts "Vcs revision: #{REV}" + STDOUT.puts "Vcs version: #{VCS_VERSION}" exit end
@@ -130,7 +123,9 @@ end env = %w[ EMAIL FULLNAME EDITOR PAGER ] if env.all? { |s| ENV[s] } - env.each { |s| Kernel.const_set(s, ENV[s]) } + EDITOR = ENV['EDITOR'].to_cmd + PAGER = ENV['PAGER'].to_cmd + EMAIL = ENV['EMAIL'] else env.each { |s| LOG.error "Need #{s} in the environement" unless ENV[s] } exit Index: vcs/src/vcs.rb --- vcs/src/vcs.rb (revision 206) +++ vcs/src/vcs.rb (working copy) @@ -1,234 +0,0 @@ -# Author:: Nicolas Pouillard ertai@lrde.epita.fr. -# Copyright:: Copyright (c) 2004 LRDE. All rights reserved. -# License:: GNU General Public License (GPL). - -# $LastChangedBy: ertai $ -# $Id: header 98 2004-09-29 12:07:43Z ertai $ - -require 'set' -require 'commands' - -# The abstract class for a Vcs wrapper. -# Conventions: -# example: -# svn checkout http://foo.bar/proj # alias -# vcs-svn checkout http://foo.bar/proj # wrapper -# vcs --vcs Svn checkout http://foo.bar/proj # manual -# -# checkout -# checkout_ -# checkout! -# checkout_! -# -class Vcs - - class Failure < Exception - end - - def initialize ( aCmd ) - @cmd = aCmd.to_cmd - @handlers = Set.new - @runner = Commands::Runners::System.new - @runner.subscribe_hook(:failure) do |data| - if data.status - LOG.error { "exit(#{data.status.exitstatus})" } - else - LOG.fatal { 'no exit status' } - end - end - @runner.subscribe_hook(:display_command) do |cmd| - LOG.debug { "running: #{cmd.to_sh}" } - end - @out, @err = STDOUT, STDERR - end - - def self.add_basic_method ( meth ) - class_eval <<-end_eval - def #{meth}! ( *args ) - run!("#{meth}", *args) - end - def #{meth}_! ( *args ) - run!("#{meth}", *args) - end - end_eval - end - - @@all_commands = {} - @@all_aliases = Set.new - - def self.alias_command ( m1, m2 ) - m2 = m2.to_s - @@all_commands[m2] ||= Set.new - @@all_commands[m2] << m1.to_s - @@all_aliases << m1 - class_eval <<-end_eval - def #{m1} ( *args ) - #{m2}(*args) - end - def #{m1}_ ( *args ) - #{m2}_(*args) - end - def #{m1}! ( *args ) - #{m2}!(*args) - end - def #{m1}_! ( *args ) - #{m2}_!(*args) - end - end_eval - end - - attr_accessor :out, :err, :out_path, :err_path - - @@checkers = Set.new - - def run! ( *args ) - cmd = @cmd + args - if @out_path.nil? - cmd = cmd > [@out, @err] - else - cmd = cmd > [@out_path, @err_path] - end - cmd.run(@runner) - end - - def sub_vcs - copy = dup - copy.out_path = TempPath.new - copy.err_path = TempPath.new - copy.out = copy.out_path.open('w') - copy.err = copy.err_path.open('w') - copy - end - - def run ( *args ) - sub_vcs.run!(*args) - end - - %w[ checkout delete diff status log add update commit ].each do |m| - add_basic_method(m) - end - - def method_missing ( meth, *args ) - meth = meth.to_s - if meth =~ /^(.*)!$/ - no_bang = $1 - if respond_to? no_bang - LOG.warn { "Unefficient method call (#{no_bang}), " + - "prefer define methods with a `!'" } - send(no_bang, *args).each do |line| - puts line - end - else - LOG.warn { "unknown method #{meth}" } - run!(no_bang.sub(/_$/, ''), *args) - end - else - with_bang = meth + '!' - if respond_to? with_bang - copy = sub_vcs - res = copy.send(with_bang, *args) - if res.nil? - copy.out.close - copy.out_path - else - res - end - else - LOG.warn { "unknown method #{meth}" } - run!(meth.sub(/_$/, ''), *args) - end - end - end - - def help! ( *args ) - return help_!(*args) unless args.empty? - @out.puts " - |usage: #{@cmd.command} <subcommand> [options] [args] - |Type '#{@cmd.command} help <subcommand>' for help on a specific subcommand. - | - |Most subcommands take file and/or directory arguments, recursing - |on the directories. If no arguments are supplied to such a - |command, it recurses on the current directory (inclusive) by default. - | - |Available subcommands:".head_cut! - cmds = [] - methods.each do |meth| - next if meth =~ /_!?$/ - next unless meth =~ /^(.+)!$/ - cmd = $1 - next if cmd == 'run' - next if @@all_aliases.include? cmd.to_sym - cmds << cmd - end - cmds.sort! - cmds.each do |cmd| - if @@all_commands.has_key? cmd - aliases = @@all_commands[cmd].sort.join(', ') - @out.puts " - #{cmd} (alias #{aliases})" - else - @out.puts " - #{cmd}" - end - end - end - - alias_command :ann, :blame - alias_command :annotate, :blame - alias_command :praise, :blame - alias_command :co, :checkout - alias_command :ci, :commit - alias_command :cp, :copy - alias_command :del, :delete - alias_command :remove, :delete - alias_command :rm, :delete - alias_command :di, :diff - alias_command :h, :help - alias_command :ls, :list - alias_command :mv, :move - alias_command :rename, :move - alias_command :ren, :move - alias_command :pdel, :propdel - alias_command :pd, :propdel - alias_command :pedit, :propedit - alias_command :pe, :propedit - alias_command :pget, :propget - alias_command :pg, :propget - alias_command :plist, :proplist - alias_command :pl, :proplist - alias_command :pset, :propset - alias_command :ps, :propset - alias_command :st, :status - alias_command :stat, :status - alias_command :sw, :switch - alias_command :up, :update - - # Cvs Alias - alias_command :new, :add - alias_command :rcs, :admin - alias_command :get, :checkout - alias_command :rlog, :log - alias_command :patch, :rdiff - alias_command :rfreeze, :rtag - alias_command :freeze, :tag - - # Prcs Alias - alias_command :checkin, :commit - alias_command :populate, :add - - def error_handling ( meth ) - @handlers << meth - end - - def call_handlers - @handlers.each { |meth| send(meth) } - end - - def self.add_conf_checker ( meth ) - @@checkers << meth - end - - def call_conf_checkers - @@checkers.each { |meth| send(meth) } - end - -end # class Vcs - Index: vcs/src/message.rb --- vcs/src/message.rb (revision 206) +++ vcs/src/message.rb (working copy) @@ -1,69 +0,0 @@ -# Author:: Nicolas Pouillard ertai@lrde.epita.fr. -# Copyright:: Copyright (c) 2004 LRDE. All rights reserved. -# License:: GNU General Public License (GPL). - -# $LastChangedBy: ertai $ -# $Id: header 98 2004-09-29 12:07:43Z ertai $ - -require 'vcs/vcs' -require 'vcs/changelog' - -class Vcs - def diffw! ( *args ) - diff!(*args) - end -end - -class Svn - def diffw! ( *args ) - diff! '--diff-cmd', 'diff', '-x', '-NPbuw', *args - end -end - -class Vcs - - @@message = Pathname.new(',message') - - def print_body ( file, options ) - LOG.warn "Creating a new `#{file}' file" - file.open('w') do |f| - f.puts options.to_yaml - f.puts '---' - f.puts - f.print message.read - end - end - private :print_body - - def message ( *args ) - error_handling :message_failed - - unless @@message.exist? - cl = mkchangelog(*args) - TempPath.new('message') do |tmp| - tmp.open('w') do |f| - f.puts 'Index: ChangeLog' - f.print cl.read.sub(/^\d+-\d+-\d+/, 'from') - f.puts - f.print diffstat(*args).read - f.puts - diffw_from_status(*args).each_line do |line| - f.print line if line !~ /^=+$/ - end - end - tmp.mv(@@message) - end - end - @@message.open('r') - end - - alias_command :msg, :message - - def message_failed - if @@message.exist? - LOG.info "#{@@message}: Contains the generated message" - LOG.info ' (the ChangeLog entry, the diffstat, the diff)' - end - end - -end # class Vcs Index: vcs/AUTHORS --- vcs/AUTHORS (revision 0) +++ vcs/AUTHORS (revision 0) @@ -0,0 +1,6 @@ +--- +Vcs was written by and with the assistance of: + + - Nicolas Pouillard ertai@lrde.epita.fr: + - Initial Design + - Maintenance Index: vcs/src/tools.rb --- vcs/src/tools.rb (revision 206) +++ vcs/src/tools.rb (working copy) @@ -1,22 +0,0 @@ -# Author:: Nicolas Pouillard ertai@lrde.epita.fr. -# Copyright:: Copyright (c) 2004 LRDE. All rights reserved. -# License:: GNU General Public License (GPL). - -# $LastChangedBy: ertai $ -# $Id: header 98 2004-09-29 12:07:43Z ertai $ - -require 'yaml' -module YAML - - def self.chop_header ( io ) - aStr = io.gets - raise Exception, "First line is not valid: `#{aLine}'" unless aStr =~ /^---/ - io.each do |aLine| - break if aLine =~ /^---/ - aStr += aLine - end - YAML::load(aStr) - end - -end # module YAML - Index: vcs/src/ask.rb --- vcs/src/ask.rb (revision 206) +++ vcs/src/ask.rb (working copy) @@ -1,101 +0,0 @@ -# Author:: Nicolas Pouillard ertai@lrde.epita.fr. -# Copyright:: Copyright (c) 2004 LRDE. All rights reserved. -# License:: GNU General Public License (GPL). - -# $LastChangedBy: ertai $ -# $Id: header 98 2004-09-29 12:07:43Z ertai $ - -ANSWERS = [ :y, :n ] -ANSWER_NOT_VALID = 'Not a valid answer, please answer correctly' - -# `ask', ask the user to answer, to your question. -# -# Example: -# ask('Commiting, are you sure', :n) -# -# produce => Commiting, are you sure (y/N): -# and wait your answer. -def ask ( aQuestion, theDefaultAnswer=:y, cin=STDIN, cout=STDOUT, cerr=STDERR ) - - yn = case theDefaultAnswer - when :y then ' [Y/n]: ' - when :n then ' [y/N]: ' - else raise ArgumentError, "not valid default answer #{theDefaultAnswer}" - end - - loop do - cout.print aQuestion, yn - cout.flush - - answer = cin.readline.chomp.downcase - - return theDefaultAnswer if answer.empty? - - answer = answer.to_sym - - return answer if ANSWERS.include? answer - - cerr.puts ANSWER_NOT_VALID - cout.puts - end - -end - -if defined? TEST_MODE or $0 == __FILE__ - -require 'test/unit' -class AskTest < Test::Unit::TestCase - - def ask_checker ( question, default, answer, ref, out, err ) - require 'stringio' - cin, cout, cerr = StringIO.new, StringIO.new, StringIO.new - cin.puts answer - cin.rewind - res = ask(question, default, cin, cout, cerr) - cout.rewind - cerr.rewind - assert_equal(res, ref, 'bad return value') - assert_equal(cout.readlines.join, out, 'bad standard output') - assert_equal(cerr.readlines.join, err, 'bad error output') - end - - def test_bad_default - assert_raise(ArgumentError) { ask_checker('Q', :foo, '', :y, [], []) } - assert_nothing_raised do - ask_checker('Q', :y, 'y', :y, 'Q [Y/n]: ', '') - end - assert_nothing_raised do - ask_checker('Q', :n, 'y', :y, 'Q [y/N]: ', '') - end - end - - def test_valid_default_yes - ask_checker('Q', :y, 'y', :y, 'Q [Y/n]: ', '') - ask_checker('Q', :y, 'Y', :y, 'Q [Y/n]: ', '') - ask_checker('Q', :y, 'n', :n, 'Q [Y/n]: ', '') - ask_checker('Q', :y, 'N', :n, 'Q [Y/n]: ', '') - ask_checker('Q', :y, '', :y, 'Q [Y/n]: ', '') - end - - def test_valid_default_no - ask_checker('Q', :n, 'y', :y, 'Q [y/N]: ', '') - ask_checker('Q', :n, 'Y', :y, 'Q [y/N]: ', '') - ask_checker('Q', :n, 'n', :n, 'Q [y/N]: ', '') - ask_checker('Q', :n, 'N', :n, 'Q [y/N]: ', '') - ask_checker('Q', :n, '', :n, 'Q [y/N]: ', '') - end - - def test_invalid_answer - ask_checker('Q', :n, "bad\ny", :y, - "Q [y/N]: \nQ [y/N]: ", ANSWER_NOT_VALID + "\n") - ask_checker('Q', :y, "ad\n\n", :y, - "Q [Y/n]: \nQ [Y/n]: ", ANSWER_NOT_VALID + "\n") - end - - def test_ask1 - ask_checker('Q', :y, 'y', :y, 'Q [Y/n]: ', '') - end - -end # class AskTest - -end Index: vcs/SPEC.dyn.yml --- vcs/SPEC.dyn.yml (revision 0) +++ vcs/SPEC.dyn.yml (revision 0) @@ -0,0 +1,9 @@ +--- !ruby/object:OpenStruct +table: + :url: https://svn.lrde.epita.fr/svn/lrdetools/trunk/vcs + :date: "Fri, 01 Jul 2005" + :version: !ruby/object:Version + build: 148 + major: 0 + minor: 2 + revision: 206 Index: vcs/src/prcs.rb --- vcs/src/prcs.rb (revision 206) +++ vcs/src/prcs.rb (working copy) @@ -1,21 +0,0 @@ -# Author:: Nicolas Pouillard ertai@lrde.epita.fr. -# Copyright:: Copyright (c) 2004 LRDE. All rights reserved. -# License:: GNU General Public License (GPL). - -# $LastChangedBy: ertai $ -# $Id: header 98 2004-09-29 12:07:43Z ertai $ - -require 'vcs/vcs' - -class Prcs < Vcs - - def initialize ( aCmd='prcs' ) - super - end - - %w[ admin ].each do |m| - add_basic_method(m) - end - -end # class Prcs - Index: vcs/src/conflict.rb --- vcs/src/conflict.rb (revision 206) +++ vcs/src/conflict.rb (working copy) @@ -1,21 +0,0 @@ -class Vcs - - def mk_conflicts_list - ls = status.output.readlines.grep(/^C/).map! { |s| s[/^C\s+(.*)/, 1] } - raise "no conflicts" if ls.empty? - ls - end - - def edit_conflicts! - edit! mk_conflicts_list - end - - def resolve_conflicts! - conflicts = mk_conflicts_list - question = "Resolve these conflicts: \n - #{conflicts.join("\n - ")}\n" - if ask(question, :n, STDIN, @out, @err) == :y - return resolved(conflicts) - end - end - -end # class Vcs Index: vcs/SPEC.yml --- vcs/SPEC.yml (revision 0) +++ vcs/SPEC.yml (revision 0) @@ -0,0 +1,35 @@ +--- +Author: Nicolas Pouillard +License: GNU General Public License (GPL) +Revision: '$Id$' + +name: vcs + +title: Vcs -- A wrapper over any version control system +summary: A wrapper over any version control system +description: | + Version control systems (Subversion, CVS, PRCS...), however useful, are not + very extensible: adding new features can be cumbersome, especially if you + want them for different such systems at once. Vcs provide a simple dynamic + hierarchy for Version Control Systems. +homepage: http://rubyforge.org/projects/vcs + +rdoc_dir: doc/html +tags_url: https://svn.lrde.epita.fr/svn/lrdetools/tags + +commit_command: ltci + +rdoc_files: !filelist + - README + - AUTHORS + - lib/vcs/**/*.rb + +pkg_files: !filelist + - lib/vcs/**/*.rb + - bin/**/* + - '[A-Z]*' + +executables: [ vcs, vcs-svn, vcs-cvs, vcs-prcs ] + +dependencies: + ruby_ex: ~> 0.1.3 Index: vcs/src/news.rb --- vcs/src/news.rb (revision 206) +++ vcs/src/news.rb (working copy) @@ -1,118 +0,0 @@ -# Author:: Nicolas Pouillard ertai@lrde.epita.fr. -# Copyright:: Copyright (c) 2004 LRDE. All rights reserved. -# License:: GNU General Public License (GPL). - -# $LastChangedBy: ertai $ -# $Id: header 98 2004-09-29 12:07:43Z ertai $ - -require 'vcs/tools' -require 'vcs/message' - -class Vcs - - NEWS = Pathname.new(',news') - - def parse_news_options ( *args ) - require 'optparse' - result = - { - :from => FULL_EMAIL, - :groups => [], - :server => ENV['NNTPSERVER'], - } - if !args.nil? and !args.empty? and args[0].is_a?(Hash) - return result.merge!(args[0]) - end - OptionParser.new do |opts| - opts.separator '' - opts.on('-g', '--group NAME', 'Choose a news group') do |aString| - result[:groups] << aString - end - opts.on('-s', '--server NAME', 'Choose a news server') do |aString| - result[:server] = aString - end - opts.on('-S', '--subject NAME', 'Choose your news subject') do |aString| - result[:subject] = aString.sub(/.?$/, '.') - end - opts.on_tail('-h', '--help', 'Show this message') do - puts opts - exit - end - end.parse!(args) - raise Failure, 'No news group' if result[:groups].empty? - raise Failure, 'No news server' if result[:server].nil? - raise Failure, 'No news subject' if result[:subject].nil? - result - end - protected :parse_news_options - - def check_line ( anIO, aRegex ) - line = anIO.readline.chomp! - LOG.debug('news') { "Server: #{line}" } - unless line =~ aRegex - LOG.error('news') { "Bad answer: #{line}" } - @news_status = 'Error.' - end - end - private :check_line - - # - # Post the news. - # - def news! ( *args ) - error_handling :news_failed - - print_body(NEWS, parse_news_options(*args)) unless NEWS.exist? - - @news_status = 'Sent.' - NEWS.open('r') do |file| - opt = YAML::chop_header(file) - server, port = opt[:server].split(/:/) - port ||= 119 - LOG.info('news') { "Nntp Server: #{server}:#{port}" } - if ask("Post a news, with this subject: #{opt[:subject]}\n" + - " to #{opt[:groups].join(', ')}\n from #{opt[:from]}\n" + - 'Are you sure?', :y) == :n - LOG.error('news') { 'Aborting' } - exit - end - require 'socket' - TCPSocket.open(server, port) do |f| - check_line(f, /^200/) - f.puts 'post' - check_line(f, /^340/) - f.puts "Newsgroups: #{opt[:groups].join(', ')}" - f.puts "From: #{opt[:from]}" - f.puts "Subject: #{opt[:subject]}" - f.puts - file.each do |line| - f.print line.gsub(/^./, ' .') - end - f.puts '.' - check_line(f, /^240/) - f.puts 'quit' - check_line(f, /^205/) - end - end - NEWS.delete - @out.puts @news_status - end - - def news_failed - if defined? NEWS and NEWS.exist? - LOG.info "#{NEWS}: Contains the generated news" + - "(generated from #{@@message})" - end - end - - def news_conf_checker - %w[ NNTPSERVER ].each do |var| - if ENV[var].nil? or ENV[var].empty? - LOG.error "environment variable `#{var}' not set" - end - end - end - - add_conf_checker :news_conf_checker - -end # class Vcs Index: vcs/Rakefile --- vcs/Rakefile (revision 206) +++ vcs/Rakefile (working copy) @@ -1,73 +1,8 @@ -require 'rubygems' -require 'rake' -require 'rake/testtask' -require 'rake/packagetask' -require 'rake/rdoctask' -require 'rake/gempackagetask' -require 'rake/contrib/rubyforgepublisher' - -PKG_VERSION = "0.2.#{`vcs-svn rev`.chomp}" - -PKG_FILES = FileList[*%w" - src/**/*.rb - ruby_ex/**/*.rb - bin/**/* - doc/**/* - [A-Z]* -"].exclude(/\b.svn\b|..*.sw[op]$|~$|README/) - -desc 'Default Task' -task :default => :package - -desc 'Publish to RubyForge' -task :rubyforge do - Rake::RubyForgePublisher.new('vcs', 'ertai').upload -end - - -Rake::RDocTask.new('doc') do |rdoc| - rdoc.title = 'Vcs -- A wrapper over any version control system' - rdoc.template = 'kilmer' - #rdoc.template = 'doc/jamis' - rdoc.options << '--line-numbers' << '--inline-source' - #rdoc.rdoc_files.add('src/vcs.rb', 'src/**/*.rb') - rdoc.rdoc_files.add('src/**/*.rb') - #rdoc.main = -end - - -# The Gem specification -spec = Gem::Specification.new do |s| - s.platform = Gem::Platform::RUBY - s.name = 'vcs' - s.version = PKG_VERSION - s.summary = 'A wrapper over any version control system' - s.description = ' - Version control systems (Subversion, CVS, PRCS...), however useful, - are not very extensible: adding new features can be cumbersome, especially - if you want them for different such systems at once. - Vcs provide a simple dynamic hierarchy for Version Control Systems. - ' - - s.bindir = 'bin' - s.executables = %w[ vcs vcs-svn vcs-cvs vcs-prcs ] - s.default_executable = 'vcs' - s.files = PKG_FILES.to_a - s.require_path = 'src' - s.autorequire = 'vcs' - - s.has_rdoc = true - s.author = 'Nicolas Pouillard' - s.email = 'ertai@lrde.epita.fr' - s.homepage = 'https://svn.lrde.epita.fr/svn/lrdetools/trunk/vcs/' - s.rubyforge_project = s.name -end - -# Create compressed packages -Rake::GemPackageTask.new(spec) do |p| - p.gem_spec = spec - # p.need_tar = true - # p.need_zip = true -end - +# Author:: The TTK Team. -*- ruby -*- +# Copyright:: Copyright (c) 2005 TTK team. All rights reserved. +# License:: Ruby License +# Revision:: $Id$
+require 'rubygems' +require_gem 'core_ex' +load 'core_ex/rakefile_base.rf' Index: vcs/src/diffstat.rb --- vcs/src/diffstat.rb (revision 206) +++ vcs/src/diffstat.rb (working copy) @@ -1,30 +0,0 @@ -# Author:: Nicolas Pouillard ertai@lrde.epita.fr. -# Copyright:: Copyright (c) 2004 LRDE. All rights reserved. -# License:: GNU General Public License (GPL). -# Revision:: $Id$ - -require 'vcs/vcs' - -class Vcs - @@diffstat = 'diffstat'.to_cmd - - # Use the diffstat command to - # display statitics on your patch. - def diffstat! ( *a ) - check_diffstat - data_diff = diff(*a) - cmd = @@diffstat < data_diff.output.open > [@out_path, @err_path] - cmd.sys - end - alias_command :ds, :diffstat - - def check_diffstat - unless `diffstat -V` =~ /diffstat version/ - raise ArgumentError, 'The `diffstat' tool is needed by Vcs.diffstat' - end - end - - add_conf_checker :check_diffstat - -end # class Vcs - Index: vcs/lib/vcs/edit.rb --- vcs/lib/vcs/edit.rb (revision 0) +++ vcs/lib/vcs/edit.rb (revision 0) @@ -0,0 +1,15 @@ +# Author:: Nicolas Pouillard ertai@lrde.epita.fr. +# Copyright:: Copyright (c) 2004 LRDE. All rights reserved. +# License:: GNU General Public License (GPL). +# Revision:: $Id$ + +require 'vcs/vcs' + +class Vcs + + def edit! ( *files ) + cmd = EDITOR + files.flatten.map { |x| x.to_s } > [STDOUT, STDERR] + cmd.run(@runner) + end + +end # class Vcs
Property changes on: vcs/lib/vcs/edit.rb ___________________________________________________________________ Name: svn:keywords + Id
Index: vcs/src/svn.rb --- vcs/src/svn.rb (revision 206) +++ vcs/src/svn.rb (working copy) @@ -1,29 +0,0 @@ -# Author:: Nicolas Pouillard ertai@lrde.epita.fr. -# Copyright:: Copyright (c) 2004 LRDE. All rights reserved. -# License:: GNU General Public License (GPL). - -# $LastChangedBy: ertai $ -# $Id: header 98 2004-09-29 12:07:43Z ertai $ - -require 'vcs/vcs' -require 'vcs/tools' - -CL = Pathname.new('ChangeLog') -ADD_CL = Pathname.new(',ChangeLog') -TMP_CL = Pathname.new(',,ChangeLog') - -class Svn < Vcs - - class Failure < Vcs::Failure - end - - def initialize ( aCmd='svn' ) - super - end - - %w[ blame cat cleanup copy export import list log merge mkdir move propedit - switch resolved revert info propdel propget proplist propset ].each do |m| - add_basic_method(m) - end - -end # class Svn Index: vcs/NEWS --- vcs/NEWS (revision 0) +++ vcs/NEWS (revision 0) @@ -0,0 +1,3 @@ +New in 0.3 ...: + * help + * full stream based Index: vcs/src/revision.rb --- vcs/src/revision.rb (revision 206) +++ vcs/src/revision.rb (working copy) @@ -1,18 +0,0 @@ -# Author:: Nicolas Pouillard ertai@lrde.epita.fr. -# Copyright:: Copyright (c) 2004 LRDE. All rights reserved. -# License:: GNU General Public License (GPL). - -# $LastChangedBy: ertai $ -# $Id: header 98 2004-09-29 12:07:43Z ertai $ - -require 'vcs/svn' - -class Svn - - def revision! ( *args ) - @out.puts info.read[/^Revision:\s+(\d+)/, 1] - end - - alias_command :rev, :revision - -end # class Svn Index: vcs/src/changelog.rb --- vcs/src/changelog.rb (revision 206) +++ vcs/src/changelog.rb (working copy) @@ -1,115 +0,0 @@ -# Author:: Nicolas Pouillard ertai@lrde.epita.fr. -# Copyright:: Copyright (c) 2004 LRDE. All rights reserved. -# License:: GNU General Public License (GPL). -# Revision:: $Id: header 98 2004-09-29 12:07:43Z ertai $ - -require 'vcs/vcs' -require 'vcs/svn' - -class Svn - - @@file_st = - { - 'A' => 'New', - 'D' => 'Remove', - } - @@file_st.default = '' - - @@prop_st = - { - 'M' => 'Changed property' - } - - def mkchangelog_from_status ( *args ) - result = [] - from_status(*args) do |line, file_st, prop_st, copy_st, file| - next if file_st =~ /[?X]/ - next if file == 'ChangeLog' - ls = [] - ls << @@file_st[file_st] if @@file_st.has_key? file_st - ls << @@prop_st[prop_st].downcase if @@prop_st.has_key? prop_st - result << [file, ls.join(', ')] - end - raise Failure, 'No changes, so no ChangeLog entry.' if result.empty? - result - end - private :mkchangelog_from_status - -end # class Svn - - -class Vcs - - class MustBeFilled < Exception - attr_reader :file - def initialize ( file ) - @file = file - super("You must fill this file: `#{file.to_s}'") - end - end - - def mkchangelog! ( *args ) - error_handling :changelog_failed - - cl = ADD_CL - - if cl.exist? - f = cl.open('r') - if f.readline !~ /^===/ - f.rewind - return f - end - f.close - else - cl_add = mkchangelog_from_status(*args) - LOG.warn "Creating a new `#{cl}' file" - cl.open('w') do |f| - f.puts '=== Fill this file correctly and remove this line ===' - f.puts Time.now.strftime("%Y-%m-%d #{FULL_EMAIL}") - f.puts - cl_add.each do |file, str| - f.puts "\t* #{file}: #{str}." - end - end - end - - raise MustBeFilled, cl - end - - def concat_changelog! ( *args ) - error_handling :changelog_failed - - unless CL.exist? - raise Failure, "No `#{CL}', you are probably not in a valid directory." - end - - if cl = mkchangelog(*args) - - unless TMP_CL.exist? - LOG.info "Moving `#{CL}' to `#{TMP_CL}' ..." - CL.rename(TMP_CL) - end - - CL.open('w') do |file| - LOG.info "Prepending `#{ADD_CL}' to `#{CL}' ..." - file.print cl.read - file.puts - file.print TMP_CL.read - end - - end - end - - def changelog_failed - if TMP_CL.exist? - LOG.info "Restoring `#{CL}' from `#{TMP_CL}' ..." - TMP_CL.rename(CL) - end - LOG.info "#{ADD_CL}: Contains your ChangeLog entry" if ADD_CL.exist? - end - - alias_command :mkcl, :mkchangelog - alias_command :ctcl, :concat_changelog - -end # class Vcs - Index: vcs/src/status.rb --- vcs/src/status.rb (revision 206) +++ vcs/src/status.rb (working copy) @@ -1,17 +0,0 @@ -# Author:: Nicolas Pouillard ertai@lrde.epita.fr. -# Copyright:: Copyright (c) 2004 LRDE. All rights reserved. -# License:: GNU General Public License (GPL). -# Revision:: $Id$ - -class Svn - - def from_status ( *args, &block ) - status(*args).output.each_line do |line| - next unless line =~ /^.{5} / - m = /^(.)(.).(.).\s*(.*)$/.match(line) - block[*m.to_a] - end - end - protected :from_status - -end # class Svn Index: vcs/src/last_changed_date.rb --- vcs/src/last_changed_date.rb (revision 206) +++ vcs/src/last_changed_date.rb (working copy) @@ -1,16 +0,0 @@ -# Author:: Nicolas Pouillard ertai@lrde.epita.fr. -# Copyright:: Copyright (c) 2004 LRDE. All rights reserved. -# License:: GNU General Public License (GPL). -# $Id$ - -require 'vcs/svn' - -class Svn - - def last_changed_date! ( *args ) - @out.puts info.read[/^Last Changed Date:.*?(([^)]*)).*$/, 1] - end - - alias_command :date, :last_changed_date - -end # class Svn Index: vcs/src/diff.rb --- vcs/src/diff.rb (revision 206) +++ vcs/src/diff.rb (working copy) @@ -1,18 +0,0 @@ -# Author:: Nicolas Pouillard ertai@lrde.epita.fr. -# Copyright:: Copyright (c) 2004 LRDE. All rights reserved. -# License:: GNU General Public License (GPL). -# Revision:: $Id$ - -class Svn - - def diffw_from_status! ( *args ) - files = Set.new - from_status(*args) do |line, file_st, prop_st, cpy, file| - next if file_st =~ /[?X]/ - next if file == 'ChangeLog' - files << Pathname.new(file) - end - diffw!(*files.delete_if { |f| f.directory? }) - end - -end # class Svn Index: vcs/src/mycommit.rb --- vcs/src/mycommit.rb (revision 206) +++ vcs/src/mycommit.rb (working copy) @@ -1,86 +0,0 @@ -# Author:: Nicolas Pouillard ertai@lrde.epita.fr. -# Copyright:: Copyright (c) 2004 LRDE. All rights reserved. -# License:: GNU General Public License (GPL). - -# $LastChangedBy: ertai $ -# $Id: header 98 2004-09-29 12:07:43Z ertai $ - -require 'vcs/vcs' -require 'ask' - -class Vcs - - COMMITED = Pathname.new(',commited') - - def common_commit! ( *args, &block ) - - opts, args = args.partition { |a| a =~ /^-/ } - - update! - - unless COMMITED.exist? - - begin - mkchangelog(*args) - rescue MustBeFilled => ex - edit! ex.file - end - - message(*args) - - edit! @@message - - if ask('Committing, are you sure?', :y) == :n - commit_failed - end - - concat_changelog!(*args) - - #pager! diff - #pager! status - - args << 'ChangeLog' unless args.grep(/^[^-]/).empty? - - if commit!('-F', ADD_CL, *(opts + args)) - ADD_CL.rename(COMMITED) - TMP_CL.delete if TMP_CL.exist? - else - commit_failed - end - - update! - - else - - message(*args) - edit! @@message - - end - - - rev = revision.read.to_i - - block.call(rev) if block_given? - - LOG.info 'Deleting junk files...' - TMP_CL.delete if TMP_CL.exist? - ADD_CL.delete if ADD_CL.exist? - COMMITED.delete if COMMITED.exist? - messages = Pathname.new(',messages') - messages.mkpath unless messages.directory? - message_rev = messages + "#{@@message}.#{rev}" - LOG.info "Moving `#{@@message}' to `#{message_rev}'..." - @@message.rename(message_rev) - LOG.info "You can remove `#{message_rev}' if everything is ok." - - end - alias_command :cci, :common_commit - - def commit_failed - LOG.info "#{COMMITED}: Contains your ChangeLog entry" if COMMITED.exist? - LOG.error 'Aborting' - LOG.info 'You can rerun the same command to continue the commit' - raise 'Commit failed' - end - -end # class Vcs Index: vcs/src/cvs.rb --- vcs/src/cvs.rb (revision 206) +++ vcs/src/cvs.rb (working copy) @@ -1,21 +0,0 @@ -# Author:: Nicolas Pouillard ertai@lrde.epita.fr. -# Copyright:: Copyright (c) 2004 LRDE. All rights reserved. -# License:: GNU General Public License (GPL). - -# $LastChangedBy: ertai $ -# $Id: header 98 2004-09-29 12:07:43Z ertai $ - -require 'vcs/vcs' - -class Cvs < Vcs - - def initialize ( aCmd='cvs' ) - super - end - - %w[ rdiff rtag tag ].each do |m| - add_basic_method(m) - end - -end # class Cvs - Index: vcs/lib/vcs/vcs.rb --- vcs/lib/vcs/vcs.rb (revision 206) +++ vcs/lib/vcs/vcs.rb (working copy) @@ -29,16 +29,16 @@ @cmd = aCmd.to_cmd @handlers = Set.new @runner = Commands::Runners::System.new + @strict_runner = Commands::Runners::System.new.raise_on_failures + + display_hook = lambda { |cmd| LOG.debug { "running: #{cmd.to_sh}" } } + @runner.subscribe_hook(:failure) do |data| - if data.status - LOG.error { "exit(#{data.status.exitstatus})" } - else - LOG.fatal { 'no exit status' } - end - end - @runner.subscribe_hook(:display_command) do |cmd| - LOG.debug { "running: #{cmd.to_sh}" } + exit((data.status)? data.status.exitstatus : 1) end + @runner.subscribe_hook(:display_command, &display_hook) + @strict_runner.subscribe_hook(:display_command, &display_hook) + @out, @err = STDOUT, STDERR end
@@ -85,10 +85,15 @@ cmd = @cmd + args if @out_path.nil? cmd = cmd > [@out, @err] + if @out == STDOUT + cmd.run(@runner) + else + cmd.run(@strict_runner) + end else cmd = cmd > [@out_path, @err_path] + cmd.run(@strict_runner) end - cmd.run(@runner) end
def sub_vcs @@ -104,7 +109,16 @@ sub_vcs.run!(*args) end
- %w[ checkout delete diff status log add update commit ].each do |m| + def run_missing! ( name, orig, *args ) + if name =~ /^(.*)_$/ + run!($1, *args) + else + LOG.warn { "unknown method #{orig}" } + run!(name, *args) + end + end + + %w[ checkout help delete diff status log add update commit ].each do |m| add_basic_method(m) end
@@ -112,31 +126,16 @@ meth = meth.to_s if meth =~ /^(.*)!$/ no_bang = $1 - if respond_to? no_bang - LOG.warn { "Unefficient method call (#{no_bang}), " + - "prefer define methods with a `!'" } - send(no_bang, *args).each do |line| - puts line - end - else - LOG.warn { "unknown method #{meth}" } - run!(no_bang.sub(/_$/, ''), *args) - end + super unless respond_to? no_bang + run_missing!(no_bang, meth, *args) else with_bang = meth + '!' - if respond_to? with_bang + return run_missing!(meth, meth, *args) unless respond_to? with_bang copy = sub_vcs res = copy.send(with_bang, *args) - if res.nil? + return res unless res.nil? copy.out.close copy.out_path - else - res - end - else - LOG.warn { "unknown method #{meth}" } - run!(meth.sub(/_$/, ''), *args) - end end end
Index: vcs/src/mail.rb --- vcs/src/mail.rb (revision 206) +++ vcs/src/mail.rb (working copy) @@ -1,51 +0,0 @@ -# Author:: Nicolas Pouillard ertai@lrde.epita.fr. -# Copyright:: Copyright (c) 2004 LRDE. All rights reserved. -# License:: GNU General Public License (GPL). -# Revision:: $Id: header 98 2004-09-29 12:07:43Z ertai $ - -require 'vcs/vcs' -require 'sendmail' - -class Vcs - - MAIL = Sendmail::MAIL_FILE - MAILER = Sendmail.new - DEFAULT_OPTIONS = %w[ --ask --sign --mime ] - - # - # Mail. - # - def mail! ( *args ) - error_handling :mail_failed - unless MAIL.exist? - print_body(MAIL, MAILER.parse_mail_options(*(DEFAULT_OPTIONS + args))) - end - MAILER.sendmail - MAIL.delete - @out.puts 'Mail: Sent.' - end - - def mail_failed - if defined? MAIL and MAIL.exist? - LOG.info "#{MAIL}: Contains the generated mail " + - "(generated from #{@@message})" - end - end - - def mail_conf_checker - %w[ EMAIL FULLNAME SMTPSERVER ].each do |var| - if ENV[var].nil? or ENV[var].empty? - LOG.error "environment variable `#{var}' not set" - end - end - unless `gpg --version` =~ /^gpg (GnuPG)/ - LOG.error 'command not found: gpg' - end - unless File.exist?("#{ENV['HOME']}/.gnupg/secring.gpg") - LOG.error 'no private key: in your ~/.gnupg' - end - end - - add_conf_checker :mail_conf_checker - -end # class Vcs