LT 113: Rcs Wrapper: First Draft

Index: ChangeLog from Nicolas Pouillard <ertai@lrde.epita.fr> * rcs-wrapper/src, rcs-wrapper, rcs-wrapper/src/news.rb, * rcs-wrapper/bin/rcsw, rcs-wrapper/bin, rcs-wrapper/src/cvs.rb, * rcs-wrapper/src/changelog.rb, rcs-wrapper/src/revision.rb, * rcs-wrapper/src/rcs.rb, rcs-wrapper/src/prcs.rb, * rcs-wrapper/src/svn.rb, rcs-wrapper/src/message.rb, * rcs-wrapper/src/mycommit.rb, rcs-wrapper/src/mail.rb, * rcs-wrapper/src/tools.rb: New. --- Intro: > Bon voilà je n'ai pas trop le temps en ce moment de m'occuper de cet outil. Il est bien commencé et à mon goût déjà utilisable. Je vais continuer à le debugger, mais en attendant vous pouvez vous amuser avec. C'est un wrapper pour les systèmes de versions comme Svn, Cvs, Prcs, Arch... Il permet donc au minimum de faire tout ce que le système sous-jacent propose, mais l'avantage est de pouvoir l'étendre facilement. Exemples d'utilisation: - Pour plus de transparence on va faire des alias: genre: alias svn=...../rcsw, idem pour cvs, prcs... pour cela taper simplement: > `le_chemin_vers_rcsw/bin/rcsw --mk-alias` - Les commandes de svn fonctionnent toujours: > placez vous dans un répertoire svn. ex: svn status - Les commandes de base peuvent être surchargées: > par exemple `svn commit' a un comportement non interactif par défaut. Mais l'on peut tout de même appeler le véritable `svn commit'. Pour cela il y a une convention: toutes les méthodes terminant par `_' sont directement celles du système. Avec cela on peut vérifier que l'outil est bien devant le vrai svn: svn status_ - Quelques fonctionnalités: - Un des principaux avantages est la gestion des erreurs: > Par exemple on utilise une commande qui commit puis poste une news. Si le commit réussit et que la news ne passe pas, il suffit de relancer l'envoi de la news: svn news En effet chaque méthode peut conserver des fichiers, ces fichiers commencent par `,'. - Les alias de méthodes: > Tout comme svn et cvs il existe des raccourcis pour certaines méthodes et bien sûr lorsque l'on surcharge une méthode, le raccourci pointe vers la nouvelle méthode. - Quelques nouvelles méthodes: - svn revision: Renvoie le numéro de révision courante alias: rev - svn mkchangelog: Génère une entrée de ChangeLog à partir de `status' alias: mkcl - svn changelog: Concatène la nouvelle entrée au véritable ChangeLog alias: cl - svn message: Crée le contenu du message du mail ou de la news alias: msg - svn mail: Envoie un mail. - svn news: Poste une news. - Plus facile d'écrire des scripts: > Lorsque l'on veut automatiser un traitement fait avec un Rcs, il est généralement plus simple de le faire en script shell lorsque cela n'excède pas une dixaine de lignes. Après cela certains avantages des langages de script évolués nous manquent. Pourtant certaines choses très faciles peuvent devenir plus lourdes: svn commit => system("svn commit") Heureusement avec le modèle objet déjà posé cela devient plus raisonnable, comparez par exemple: svn commit => svn.commit svn info | grep '^Revision' | sed s/^Revision: // => svn.info.readlines.grep(/^Revision/)[0].sub(/^Revision: /, '').to_i - Exemple final: commit complet pour les lrde tools. commande: svn lrdetools_commit 'votre sujet pour la news' ensuite: laissez vous guider. - S'il y a des questions il y aura des réponses. Index: rcs-wrapper/src/revision.rb --- rcs-wrapper/src/revision.rb (revision 0) +++ rcs-wrapper/src/revision.rb (revision 0) @@ -0,0 +1,19 @@ +# 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 'svn' +require 'stringio' + +class Svn + + def revision ( *args ) + StringIO.new(info.readlines.grep(/^Revision:/)[0].sub(/^Revision: /, '')) + end + + alias_command :rev, :revision + +end # class Svn Index: rcs-wrapper/src/mycommit.rb --- rcs-wrapper/src/mycommit.rb (revision 0) +++ rcs-wrapper/src/mycommit.rb (revision 0) @@ -0,0 +1,69 @@ +# 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 'rcs' + +class Rcs + + def edit! ( *files ) + system(ENV['EDITOR'], *files) + end + + def common_commit! ( *args ) + + begin + changelog!(*args) + rescue MustBeFilled => ex + edit! ex.file + end + + message!(*args) + + edit! @@message + + changelog!(*args) + + #pager! diff + #pager! status + + args << 'ChangeLog' unless args.grep(/^[^-]/).empty? + + commit!(*args) + + return self.revision.readline.to_i + + end + protected :common_commit! + + + def lrdetools_commit! ( s, *args ) + + rev = common_commit!(*args) + + s = "LT #{rev}: #{s}" + + news(:groups => ['lrde.proj'], :subject => s) + + @@message.delete + + end + alias_command :ltci, :lrdetools_commit + + def test_commit! ( s, *args ) + + rev = common_commit!(*args) + + s = "Test #{rev}: #{s}" + +# news(:groups => ['local.test'], :subject => s) + mail(:to => ['ertai@lrde.epita.fr'], :subject => s) + + @@message.delete + + end + +end # class Rcs Index: rcs-wrapper/src/tools.rb --- rcs-wrapper/src/tools.rb (revision 0) +++ rcs-wrapper/src/tools.rb (revision 0) @@ -0,0 +1,51 @@ +# 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 $ + + +module WarnAndError + + def warn ( aString ) + print "#{RCSW}: warning: ", aString, "\n" + end + + def error ( aString ) + print "#{RCSW}: error: ", aString, "\n" + end + + def debug ( aString ) + print "#{RCSW}: debug: ", aString, "\n" + end + +end # module WarnAndError + + +class IO + include WarnAndError +end # class IO + + +require 'stringio' +class StringIO + include WarnAndError +end # class StringIO + + +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: rcs-wrapper/src/mail.rb --- rcs-wrapper/src/mail.rb (revision 0) +++ rcs-wrapper/src/mail.rb (revision 0) @@ -0,0 +1,77 @@ +# 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 'rcs' +require 'tools' + +class Rcs + + @@mail = Pathname.new(',mail') + + def parse_mail_options ( *args ) + require 'optparse' + result = + { + :from => EMAIL, #FULL_EMAIL, + :to => [], + :server => ENV['SMTPSERVER'] || 'localhost', + } + if !args.nil? and !args.empty? and args[0].is_a?(Hash) + args[0].each do |k,v| + result[k] = v + end + return result + end + OptionParser.new do |opts| + opts.separator '' + opts.on('-t', '--mail-to NAME', 'Choose a recipient') do |aString| + result[:to] << aString + end + opts.on('-s', '--server NAME', 'Choose a mail server') do |aString| + result[:server] = aString + end + opts.on('-S', '--subject NAME', 'Choose your mail 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 recipents' if result[:to].empty? + raise Failure, 'No mail server' if result[:server].nil? + raise Failure, 'No mail subject' if result[:subject].nil? + result + end + protected :parse_mail_options + + # + # Mail. + # + def mail ( *args ) + + print_body(@@mail, parse_mail_options(*args)) unless @@mail.exist? + + @@mail.open('r') do |file| + opt = YAML::chop_header(file) + STDERR.puts "Smtp Server: #{opt[:server]}" + require 'net/smtp' + Net::SMTP.start(opt[:server], 25) do |smtp| + smtp.open_message_stream(EMAIL, opt[:to]) do |f| + f.print "From: #{opt[:from]}\n" + f.print "Subject: #{opt[:subject]}\n" + f.print "To: #{opt[:to].join(', ')}\n" + f.print "\n" + file.each { |line| f.print line } + end + end + end + @@mail.delete + ['Mail: Sent.'] + end + +end # class Rcs Index: rcs-wrapper/src/message.rb --- rcs-wrapper/src/message.rb (revision 0) +++ rcs-wrapper/src/message.rb (revision 0) @@ -0,0 +1,44 @@ +# 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 'rcs' +require 'changelog' + +class Rcs + + @@message = Pathname.new(',message') + + def print_body ( file, options ) + STDERR.warn "Creating a new `#{file}' file" + file.open('w') do |f| + f.puts options.to_yaml + f.puts '---' + f.puts + message.each do |line| + f.print line + end + end + end + private :print_body + + def message ( *args ) + unless @@message.exist? + cl = mkchangelog + @@message.open('w') do |f| + f.puts 'Index: ChangeLog' + cl.each { |line| f.print line.sub(/^\d+-\d+-\d+/, 'from') } + f.puts + # FIXME: need to remove the ChangeLog entry in diff. + diff.each { |line| f.print line unless line =~ /^=+$/ } + end + end + @@message.open('r') + end + + alias_command :msg, :message + +end # class Rcs Index: rcs-wrapper/src/svn.rb --- rcs-wrapper/src/svn.rb (revision 0) +++ rcs-wrapper/src/svn.rb (revision 0) @@ -0,0 +1,41 @@ +# 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 'rcs' +require 'tools' + +class Svn < Rcs + + class Failure < Rcs::Failure + end + + def initialize ( aCmd='svn' ) + super + end + + %w[ blame copy list move switch revert info + propdel propget proplist propset mkdir ].each do |m| + add_basic_method(m) + end + + add_basic_method!(:propedit) + + def commit! ( *args ) + + changelog! + + if run!('commit', '--non-interactive', '-F', @@add_cl, *args) + STDERR.puts "Deleting junk files..." + @@add_cl.delete + @@tmp_cl.delete if @@tmp_cl.exist? + else + raise Failure, 'commit failed' + end + + end + +end # class Svn Index: rcs-wrapper/src/changelog.rb --- rcs-wrapper/src/changelog.rb (revision 0) +++ rcs-wrapper/src/changelog.rb (revision 0) @@ -0,0 +1,108 @@ +# 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 'rcs' +require 'svn' + +class Svn + + @@file_st = + { + 'A' => 'New', + 'D' => 'Remove', + 'M' => '' + } + + @@prop_st = + { + 'M' => 'Changed property' + } + + def mkchangelog_from_status ( *args ) + result = {} + status(*args).each do |line| + line =~ /^(.)(.).(.).\s*(.*)$/ + if $1 != '?' + file_st, prop_st, copy_st, file = @@file_st[$1], @@prop_st[$2], $3, $4 + str = '' + str += file_st if file_st + str += (file_st.nil?) ? prop_st : (', ' + prop_st.downcase) if prop_st + result[file] = str + end + end + raise Failure, 'No changes, so no ChangeLog entry.' if result.empty? + result + end + private :mkchangelog_from_status + +end # class Svn + +class Rcs + + @@cl = Pathname.new('ChangeLog') + @@add_cl = Pathname.new(',ChangeLog') + @@tmp_cl = Pathname.new(',,ChangeLog') + + 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 ) + 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) + STDERR.warn "Creating a new `#{cl}' file" + cl.open('w') do |f| + f.puts '=== Fill this file correctly and remove this line ===' + f.puts `date +"%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 changelog! ( *args ) + unless @@cl.exist? + raise Failure, 'No ChangeLog, you are probably not in a valid directory.' + end + + if cl = mkchangelog(*args) + + unless @@tmp_cl.exist? + STDERR.warn "Move ChangeLog to `#{@@tmp_cl}'" + @@cl.rename(@@tmp_cl) + end + + @@cl.open('w') do |file| + cl.each { |line| file.print line } + file.puts + IO.foreach(@@tmp_cl) { |line| file.print line } + end + + end + end + + alias_command :mkcl, :mkchangelog + alias_command :cl, :changelog + +end # class Rcs Index: rcs-wrapper/src/prcs.rb --- rcs-wrapper/src/prcs.rb (revision 0) +++ rcs-wrapper/src/prcs.rb (revision 0) @@ -0,0 +1,21 @@ +# 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 'rcs' + +class Prcs < Rcs + + def initialize ( aCmd='prcs' ) + super + end + + %w[ admin ].each do |m| + add_basic_method(m) + end + +end # class Prcs + Index: rcs-wrapper/src/rcs.rb --- rcs-wrapper/src/rcs.rb (revision 0) +++ rcs-wrapper/src/rcs.rb (revision 0) @@ -0,0 +1,155 @@ +# 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 $ + +class Class # :nodoc: + + def 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 + + def 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 + + def alias_command ( m1, m2 ) + 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 + +end # class Class + +# The abstract class for a Rcs wrapper. +# Conventions: +# example: +# svn checkout http://foo.bar/proj # normal command +# xrcs checkout http://foo.bar/proj # normal +# +# checkout +# checkout_ +# checkout! +# checkout_! +# +class Rcs + + class Failure < Exception + end + + def initialize ( aCmd ) + @cmd = aCmd + end + + def common_run ( args ) + cmd = @cmd + ' ' + args.join(' ') + STDERR.debug "running: #{cmd}" if $debug > 1 + cmd + end + private :common_run + + def run ( *args ) + IO.popen(common_run(args)) + end + + def run! ( *args ) + system(common_run(args)) + end + + %w[ checkout delete diff help status log add update ].each do |m| + add_basic_method(m) + end + + add_basic_method!(:commit) + + def method_missing ( meth, *args ) + meth = meth.to_s + if meth =~ /^(.*)!$/ + if respond_to? $1 + send($1, *args).each do |line| + puts line + end + else + STDERR.warn "unknown method #{meth}" + run!($1.sub(/_$/, ''), *args) + end + else + STDERR.warn "unknown method #{meth}" + run(meth.sub(/_$/, ''), *args) + 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 :remove, :delete + alias_command :rm, :delete + alias_command :rfreeze, :rtag + alias_command :freeze, :tag + + # Prcs Alias + alias_command :checkin, :commit + alias_command :populate, :add + +end # class Rcs + Index: rcs-wrapper/src/cvs.rb --- rcs-wrapper/src/cvs.rb (revision 0) +++ rcs-wrapper/src/cvs.rb (revision 0) @@ -0,0 +1,21 @@ +# 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 'rcs' + +class Cvs < Rcs + + def initialize ( aCmd='cvs' ) + super + end + + %w[ rdiff rtag tag ].each do |m| + add_basic_method(m) + end + +end # class Cvs + Index: rcs-wrapper/src/news.rb --- rcs-wrapper/src/news.rb (revision 0) +++ rcs-wrapper/src/news.rb (revision 0) @@ -0,0 +1,79 @@ +# 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 'tools' +require 'message' + +class Rcs + + @@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) + args[0].each do |k,v| + result[k] = v + end + return result + 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 + 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 + + # + # Post the news. + # + def news ( *args ) + print_body(@@news, parse_news_options(*args)) unless @@news.exist? + + @@news.open('r') do |file| + opt = YAML::chop_header(file) + STDERR.puts "Nntp Server: #{opt[:server]}" + require 'socket' + TCPSocket.open(opt[:server], 119) do |f| + f.puts 'post' + 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 '.' + f.puts 'quit' + end + end + @@news.delete + StringIO.new('News: Sent.') + end + +end # class Rcs Index: rcs-wrapper/bin/rcsw --- rcs-wrapper/bin/rcsw (revision 0) +++ rcs-wrapper/bin/rcsw (revision 0) @@ -0,0 +1,75 @@ +#!/usr/bin/env ruby +# 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 $ + + +# rcsw : The rcs wrapper. +# +# rcsw is a wrapper over any revision control system. + +require 'pathname' + +RCSW_PATH = Pathname.new(__FILE__).expand_path +RCSW_DIR, RCSW = RCSW_PATH.split +SRC = RCSW_DIR + '..' + 'src' +$: << SRC + + +if ARGV == ['--mk-alias'] + %w[ svn cvs prcs ].each { |x| puts "alias #{x}=#{RCSW_PATH}" } + exit +end + +$debug = ENV['RCSW_DEBUG'].to_i + +FULLNAME = ENV['FULLNAME'] || (Etc.getpwnam ENV['USER']).gecos +EMAIL = ENV['EMAIL'] +FULL_EMAIL = "#{FULLNAME} <#{EMAIL}>" +if FULLNAME.nil? or EMAIL.nil? + STDERR.error 'Need FULLNAME and EMAIL in the environement' + exit +end + +Pathname.glob(SRC + '*.rb') do |file| + puts file.basename if $debug > 4 + require file +end + +def guess_rcs + if Pathname.new('CVS').directory? + Cvs + elsif Pathname.new('.svn').directory? + Svn + elsif Pathname.new('prj').exist? + Prcs + else + raise ArgumentError, 'Can\'t guess your RCS system' + end +end + +def main + rcs = guess_rcs().new + + if ARGV.empty? + meth = :help! + else + meth = ARGV.shift.sub(/([^!])$/, '\1!') + end + + begin + rcs.send(meth, *ARGV) + rescue Exception + raise if $debug > 0 + STDERR.error $!.to_s.sub(/\.$/, '') unless $!.to_s == 'exit' + end +end + +if __FILE__ == $0 + + main() + +end Property changes on: rcs-wrapper/bin/rcsw ___________________________________________________________________ Name: svn:executable + * Index: rcs-wrapper/README --- rcs-wrapper/README (revision 0) +++ rcs-wrapper/README (revision 0) @@ -0,0 +1,100 @@ +--- + +Intro: > + Bon voilà je n'ai pas trop le temps en ce moment de m'occuper de cet outil. + Il est bien commencé et à mon goût déjà utilisable. + + Je vais continuer à le debugger, mais en attendant vous pouvez vous amuser + avec. + + C'est un wrapper pour les systèmes de versions comme Svn, Cvs, Prcs, Arch... + + Il permet donc au minimum de faire tout ce que le système sous-jacent propose, + mais l'avantage est de pouvoir l'étendre facilement. + +Exemples d'utilisation: + + - Pour plus de transparence on va faire des alias: + genre: alias svn=...../rcsw, idem pour cvs, prcs... + pour cela taper simplement: > + `le_chemin_vers_rcsw/bin/rcsw --mk-alias` + + - Les commandes de svn fonctionnent toujours: > + placez vous dans un répertoire svn. + + ex: svn status + + - Les commandes de base peuvent être surchargées: > + par exemple `svn commit' a un comportement non interactif par défaut. + + Mais l'on peut tout de même appeler le véritable `svn commit'. + + Pour cela il y a une convention: toutes les méthodes terminant par `_' + sont directement celles du système. + + Avec cela on peut vérifier que l'outil est bien devant le vrai svn: + svn status_ + + - Quelques fonctionnalités: + + - Un des principaux avantages est la gestion des erreurs: > + + Par exemple on utilise une commande qui commit puis poste une news. + Si le commit réussit et que la news ne passe pas, il suffit de + relancer l'envoi de la news: svn news + + En effet chaque méthode peut conserver des fichiers, ces fichiers + commencent par `,'. + + - Les alias de méthodes: > + + Tout comme svn et cvs il existe des raccourcis pour certaines méthodes + et bien sûr lorsque l'on surcharge une méthode, le raccourci pointe + vers la nouvelle méthode. + + - Quelques nouvelles méthodes: + + - svn revision: Renvoie le numéro de révision courante + alias: rev + + - svn mkchangelog: Génère une entrée de ChangeLog à partir de `status' + alias: mkcl + + - svn changelog: Concatène la nouvelle entrée au véritable ChangeLog + alias: cl + + - svn message: Crée le contenu du message du mail ou de la news + alias: msg + + - svn mail: Envoie un mail. + + - svn news: Poste une news. + + - Plus facile d'écrire des scripts: > + + Lorsque l'on veut automatiser un traitement fait avec un Rcs, + il est généralement plus simple de le faire en script shell + lorsque cela n'excède pas une dixaine de lignes. Après cela certains + avantages des langages de script évolués nous manquent. + Pourtant certaines choses très faciles peuvent devenir plus lourdes: + svn commit => system("svn commit") + + Heureusement avec le modèle objet déjà posé cela devient plus + raisonnable, comparez par exemple: + + svn commit => svn.commit + + svn info | grep '^Revision' | sed s/^Revision: // + + => + + svn.info.readlines.grep(/^Revision/)[0].sub(/^Revision: /, '').to_i + + - Exemple final: commit complet pour les lrde tools. + + commande: svn lrdetools_commit 'votre sujet pour la news' + + ensuite: laissez vous guider. + + - S'il y a des questions il y aura des réponses. +

"Nicolas" == Nicolas Pouillard <ertai@lrde.epita.fr> writes:
Index: ChangeLog from Nicolas Pouillard <ertai@lrde.epita.fr>
* rcs-wrapper/src, rcs-wrapper, rcs-wrapper/src/news.rb, * rcs-wrapper/bin/rcsw, rcs-wrapper/bin, rcs-wrapper/src/cvs.rb, * rcs-wrapper/src/changelog.rb, rcs-wrapper/src/revision.rb, * rcs-wrapper/src/rcs.rb, rcs-wrapper/src/prcs.rb, * rcs-wrapper/src/svn.rb, rcs-wrapper/src/message.rb, * rcs-wrapper/src/mycommit.rb, rcs-wrapper/src/mail.rb, * rcs-wrapper/src/tools.rb: New.
Coucou Nicolas, Cool ! Mais vraiment rcs n'est pas un bon nom, c'est déjà un produit. Ces utilitaires sont groupés sous deux étiquettes : - scm - vcs le premier est déjà pris par un scheme, je vote pour le second.

On 2004-10-11, Akim Demaille <akim@epita.fr> wrote:
"Nicolas" == Nicolas Pouillard <ertai@lrde.epita.fr> writes:
Index: ChangeLog from Nicolas Pouillard <ertai@lrde.epita.fr>
* rcs-wrapper/src, rcs-wrapper, rcs-wrapper/src/news.rb, * rcs-wrapper/bin/rcsw, rcs-wrapper/bin, rcs-wrapper/src/cvs.rb, * rcs-wrapper/src/changelog.rb, rcs-wrapper/src/revision.rb, * rcs-wrapper/src/rcs.rb, rcs-wrapper/src/prcs.rb, * rcs-wrapper/src/svn.rb, rcs-wrapper/src/message.rb, * rcs-wrapper/src/mycommit.rb, rcs-wrapper/src/mail.rb, * rcs-wrapper/src/tools.rb: New.
Coucou Nicolas, Salut,
Cool !
Mais vraiment rcs n'est pas un bon nom, c'est déjà un produit. Ces utilitaires sont groupés sous deux étiquettes :
- scm - vcs
le premier est déjà pris par un scheme, je vote pour le second. Ok pour vcs.
vcs-wrapper => vcsw De toute façon une fois les alias générés on en parle plus. Et à part cette question de nommage... -- Pouillard Nicolas LRDE CSI 2006 ertai@lrde.epita.fr "Emacs is a nice OS - but it lacks a good text editor. That's why I am using Vim."

"Nicolas" == Nicolas Pouillard <pouill_n@feydakins.lrde.epita.fr> writes:
le premier est déjà pris par un scheme, je vote pour le second. Ok pour vcs.
vcs-wrapper => vcsw
Euh, c'est plus précis, mais aussi plus long :) vcs power!
Et à part cette question de nommage...
J'ai pas encore eu le temps de lire/utiliser, mais je suis pressé de le faire.

"Nicolas" == Nicolas Pouillard <ertai@lrde.epita.fr> writes:
Index: ChangeLog from Nicolas Pouillard <ertai@lrde.epita.fr>
* rcs-wrapper/src, rcs-wrapper, rcs-wrapper/src/news.rb, * rcs-wrapper/bin/rcsw, rcs-wrapper/bin, rcs-wrapper/src/cvs.rb, * rcs-wrapper/src/changelog.rb, rcs-wrapper/src/revision.rb, * rcs-wrapper/src/rcs.rb, rcs-wrapper/src/prcs.rb, * rcs-wrapper/src/svn.rb, rcs-wrapper/src/message.rb, * rcs-wrapper/src/mycommit.rb, rcs-wrapper/src/mail.rb, * rcs-wrapper/src/tools.rb: New.
C'est pas cool de ne pas l'installer : c'est coûteux pour nous en effort d'utilisation, sans compter les pbs lors des mises à jour. Peux-tu mettre un Makefile.am qui va bien ? Merci !

"Nicolas" == Nicolas Pouillard <ertai@lrde.epita.fr> writes:
Index: ChangeLog from Nicolas Pouillard <ertai@lrde.epita.fr>
* rcs-wrapper/src, rcs-wrapper, rcs-wrapper/src/news.rb, * rcs-wrapper/bin/rcsw, rcs-wrapper/bin, rcs-wrapper/src/cvs.rb, * rcs-wrapper/src/changelog.rb, rcs-wrapper/src/revision.rb, * rcs-wrapper/src/rcs.rb, rcs-wrapper/src/prcs.rb, * rcs-wrapper/src/svn.rb, rcs-wrapper/src/message.rb, * rcs-wrapper/src/mycommit.rb, rcs-wrapper/src/mail.rb, * rcs-wrapper/src/tools.rb: New.
lrde-tools/trunk/rcs-wrapper % bin/rcsw --help nostromo 13:39 bin/rcsw:29: uninitialized constant Etc (NameError)

"Nicolas" == Nicolas Pouillard <ertai@lrde.epita.fr> writes:
- Pour plus de transparence on va faire des alias: genre: alias svn=...../rcsw, idem pour cvs, prcs... pour cela taper simplement: > `le_chemin_vers_rcsw/bin/rcsw --mk-alias`
Est-ce à dire qu'il regarde son $0 pour savoir sa saveur ? Si c'est le cas, ce n'est pas une bonne idée, l'histoire l'a déjà montré. Il vaut mieux --svn, --cvs etc. et installer des wrappers de ton wrappeur. Et par défaut, --auto-rcs ou whatever, examiner le rép courant pour voir si ça semble être du CVS etc.
Avec cela on peut vérifier que l'outil est bien devant le vrai svn: svn status_
Rigolo :) NB: le backslash a ce sens en sh, donc peut-être svn '\status' ?
- Un des principaux avantages est la gestion des erreurs: >
Par exemple on utilise une commande qui commit puis poste une news. Si le commit réussit et que la news ne passe pas, il suffit de relancer l'envoi de la news: svn news
En effet chaque méthode peut conserver des fichiers, ces fichiers commencent par `,'.
Tip top !
- Quelques nouvelles méthodes:
- svn revision: Renvoie le numéro de révision courante alias: rev
Cool. Mais je suis curieux de savoir le sens en CVS ;)
- svn mkchangelog: Génère une entrée de ChangeLog à partir de `status' alias: mkcl
Trop cool. Je suis curieux de le voir ce cl.
- svn changelog: Concatène la nouvelle entrée au véritable ChangeLog alias: cl
Comprends pas "la dernière entrée".
- svn message: Crée le contenu du message du mail ou de la news alias: msg
Good !
- svn mail: Envoie un mail.
- svn news: Poste une news.
Il faudrait que ceci soit automatique avec un petit fichier de conf à deux balles. Puis svn notify par exemple.
- Exemple final: commit complet pour les lrde tools.
commande: svn lrdetools_commit 'votre sujet pour la news'
ensuite: laissez vous guider.
Curieux de voir tout ça !
@@ -0,0 +1,19 @@ +# Author:: Nicolas Pouillard <ertai@lrde.epita.fr>. +# Copyright:: Copyright (c) 2004 LRDE. All rights reserved. +# License:: GNU General Public License (GPL).
:: ?? Ffaauutt aarrêêtteerr llee cc++++. Est-ce que ton status garantit une sortie "std" qq soit le vcs dessous ? Est-ce que mkcl est au dessus de ce status ?

On 2004-10-18, Akim Demaille <akim@epita.fr> wrote:
"Nicolas" == Nicolas Pouillard <ertai@lrde.epita.fr> writes:
- Pour plus de transparence on va faire des alias: genre: alias svn=...../rcsw, idem pour cvs, prcs... pour cela taper simplement: > `le_chemin_vers_rcsw/bin/rcsw --mk-alias`
Est-ce à dire qu'il regarde son $0 pour savoir sa saveur ?
Si c'est le cas, ce n'est pas une bonne idée, l'histoire l'a déjà montré. Il vaut mieux --svn, --cvs etc. et installer des wrappers de ton wrappeur. Et par défaut, --auto-rcs ou whatever, examiner le rép courant pour voir si ça semble être du CVS etc.
Non, non c'est ce qu'il fait il regarde dans le repertoire courant pour savoir ce qu'il faut faire. Les alias sont la juste pour rendre le systeme transparent et grader la completion active ;)
Avec cela on peut vérifier que l'outil est bien devant le vrai svn: svn status_
Rigolo :)
NB: le backslash a ce sens en sh, donc peut-être
svn '\status' ?
oui mais une methode ruby ne peut contenir de '\' mais à la rigeur cela peut etre un sucre.
- Un des principaux avantages est la gestion des erreurs: >
Par exemple on utilise une commande qui commit puis poste une news. Si le commit réussit et que la news ne passe pas, il suffit de relancer l'envoi de la news: svn news
En effet chaque méthode peut conserver des fichiers, ces fichiers commencent par `,'.
Tip top !
- Quelques nouvelles méthodes:
- svn revision: Renvoie le numéro de révision courante alias: rev
Cool. Mais je suis curieux de savoir le sens en CVS ;)
Definit seulement pour Svn pour l'instant mais cela doit etre faisable.
- svn mkchangelog: Génère une entrée de ChangeLog à partir de `status' alias: mkcl
Trop cool. Je suis curieux de le voir ce cl.
- svn changelog: Concatène la nouvelle entrée au véritable ChangeLog alias: cl
Comprends pas "la dernière entrée".
Dans ,ChangeLog tu as la nouvelle entree du ChangeLog generee avec mkchangelog et modifie par tes soins. Et dans ChangeLog tu as ton ChangeLog. svn changelog concatene les deux tout simplement.
- svn message: Crée le contenu du message du mail ou de la news alias: msg
Good !
- svn mail: Envoie un mail.
- svn news: Poste une news.
Il faudrait que ceci soit automatique avec un petit fichier de conf à deux balles. Puis svn notify par exemple.
Idee interessante.
- Exemple final: commit complet pour les lrde tools.
commande: svn lrdetools_commit 'votre sujet pour la news'
ensuite: laissez vous guider.
Curieux de voir tout ça !
@@ -0,0 +1,19 @@ +# Author:: Nicolas Pouillard <ertai@lrde.epita.fr>. +# Copyright:: Copyright (c) 2004 LRDE. All rights reserved. +# License:: GNU General Public License (GPL).
:: ??
Ffaauutt aarrêêtteerr llee cc++++.
mmoorrtt ddee rriirree.
Est-ce que ton status garantit une sortie "std" qq soit le vcs dessous ? Est-ce que mkcl est au dessus de ce status ?
mkcl est definit dans Rcs et ce base sur status au format svn. il reste donc a surcharger status dans les autre vcs. -- Pouillard Nicolas LRDE CSI 2006 ertai@lrde.epita.fr "Emacs is a nice OS - but it lacks a good text editor. That's why I am using Vim."

"Nicolas" == Nicolas Pouillard <pouill_n@feydakins.lrde.epita.fr> writes:
- svn revision: Renvoie le numéro de révision courante alias: rev
Cool. Mais je suis curieux de savoir le sens en CVS ;)
Definit seulement pour Svn pour l'instant mais cela doit etre faisable.
Euh, non, pas vraiment : chaque fichier a son propre numéro de révision, aucun n'existe pour le projet.

On 2004-10-19, Akim Demaille <akim@epita.fr> wrote:
"Nicolas" == Nicolas Pouillard <pouill_n@feydakins.lrde.epita.fr> writes:
- svn revision: Renvoie le numéro de révision courante alias: rev
Cool. Mais je suis curieux de savoir le sens en CVS ;)
Definit seulement pour Svn pour l'instant mais cela doit etre faisable.
Euh, non, pas vraiment : chaque fichier a son propre numéro de révision, aucun n'existe pour le projet.
Ah oui, c'est vrai. Mais cela reste pratique pour svn. -- Pouillard Nicolas LRDE CSI 2006 ertai@lrde.epita.fr "Emacs is a nice OS - but it lacks a good text editor. That's why I am using Vim."
participants (3)
-
Akim Demaille
-
Nicolas Pouillard
-
Nicolas Pouillard