Class Vcs
In: lib/vcs/diff.rb
lib/vcs/conflict.rb
lib/vcs/message.rb
lib/vcs/common_commit.rb
lib/vcs/junk.rb
lib/vcs/opt_parse.rb
lib/vcs/edit.rb
lib/vcs/mail.rb
lib/vcs/add.rb
lib/vcs/form.rb
lib/vcs/news.rb
lib/vcs/delete.rb
lib/vcs/vcs.rb
lib/vcs/url.rb
lib/vcs/back.rb
lib/vcs/environment.rb
lib/vcs/status.rb
lib/vcs/changelog.rb
lib/vcs/last_changed_date.rb
lib/vcs/script.rb
lib/vcs/version.rb
lib/vcs/diffstat.rb
Parent: Object
Author:Nicolas Pouillard <ertai@lrde.epita.fr>.
Copyright:Copyright © 2006 LRDE. All rights reserved.
License:GNU General Public License (GPL).
Revision:$Id$

Methods

Classes and Modules

Class Vcs::Failure
Class Vcs::Logger
Class Vcs::OptParse
Class Vcs::OptionController
Class Vcs::StatusEntry
Class Vcs::Switch
Class Vcs::VcsCmdData
Class Vcs::VcsCmdDataFactory

Constants

Message = ',message'.to_path unless defined? Message
MAIL = Sendmail::MAIL_FILE unless defined? MAIL
IForm = ',iform'.to_path unless defined? Vcs::IForm
Form = ',form'.to_path unless defined? Vcs::Form
NEWS = ',news'.to_path unless defined? NEWS
CL = Pathname.new('ChangeLog') unless defined? CL
TMP_CL = Pathname.new(',,ChangeLog') unless defined? TMP_CL
LogEntry = ',log'.to_path unless defined? LogEntry
Version = ::Version.parse("dev-util/vcs-0.5_beta4")

Attributes

cmd_data  [R] 

Public Class methods

[Source]

# File lib/vcs/vcs.rb, line 354
  def self.add_basic_method ( meth )
    class_eval "def \#{meth}! ( *args )\nrun!(\"\#{meth}\", *args)\nend\ndef \#{meth}_! ( *args )\nrun!(\"\#{meth}\", *args)\nend\n"
  end

[Source]

# File lib/vcs/vcs.rb, line 665
    def add_conf_checker ( meth=nil, &block )
      @@checkers << ((block.nil?)? meth : block)
    end

[Source]

# File lib/vcs/vcs.rb, line 369
  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 "def \#{m1} ( *args )\n\#{m2}(*args)\nend\nunless method_defined? :\#{m1}\ndef \#{m1}_ ( *args )\n\#{m2}_(*args)\nend\nend\ndef \#{m1}! ( *args )\n\#{m2}!(*args)\nend\nunless method_defined? :\#{m1}!\ndef \#{m1}_! ( *args )\n\#{m2}_!(*args)\nend\nend\n"
  end

[Source]

# File lib/vcs/vcs.rb, line 679
    def classify ( file, status=nil )
      if status and category = Vcs.symbol_category[status]
        return category unless category == :unrecognize
      end
      Vcs.user_defined_categories.each do |category|
        return category if Vcs.user_conf_match(category, file)
      end
      return :unrecognize
    end

[Source]

# File lib/vcs/vcs.rb, line 689
    def color? ( &auto_block )
      case color = Vcs.user_conf.color
        when :never  then return false
        when :auto, :xmas_tree
          return (auto_block.nil?)? false : auto_block[]
        when :always then return true
        else raise ArgumentError, "Bad value for `color' (#{color})"
      end
    end

Set the given method as default commit action, use commit_ for the old one This method can be called just once to avoid conflicts

[Source]

# File lib/vcs/vcs.rb, line 728
    def default_commit ( meth )
      just_once do
        alias_command :commit, meth
        alias_command :ci, meth
      end
    end

[Source]

# File lib/vcs/vcs.rb, line 406
  def self.delegate_to_cmd_data ( *syms )
    syms.flatten.each do |meth|
      define_method(meth) do |*a|
        raise if block_given?
        @cmd_data.out_io.send(meth, *a)
      end
    end
  end

[Source]

# File lib/vcs/environment.rb, line 14
    def editor
      env('EDITOR').to_cmd
    end

[Source]

# File lib/vcs/environment.rb, line 33
    def env ( name, &block )
      return @@vars[name] if @@vars.has_key? name
      @@vars[name] =
        if var = ENV[name]
          var
        elsif block.nil?
          logger.error "Need #{name} in the environement"
          @@env_status = false
          "!!! #{name} not set !!!"
        else
          default = block[]
          logger.warn "Need #{name} in the environement (default: #{default})"
          ENV[name] = default
          default
        end
    end

[Source]

# File lib/vcs/environment.rb, line 22
    def full_email
      "#{fullname}  <#{email}>"
    end

[Source]

# File lib/vcs/environment.rb, line 10
    def fullname
      env('FULLNAME') { Etc.getpwnam(user).gecos.gsub(/,+$/, '') }
    end

[Source]

# File lib/vcs/vcs.rb, line 699
    def interactive?
      user_conf.interactive
    end

[Source]

# File lib/vcs/vcs.rb, line 711
    def merge_user_conf ( conf )
      conf = YAML.load(conf.read) if conf.is_a? Pathname
      conf.each do |k, v|
        v = v.to_sym if v.is_a? String
        user_conf.send("#{k}=", (v.is_a? Array)? ((user_conf.send(k) || []) + v) : v)
      end
    end

[Source]

# File lib/vcs/environment.rb, line 26
    def method_missing ( meth )
      env meth.to_s.upcase
    end

[Source]

# File lib/vcs/vcs.rb, line 318
  def initialize ( aCmd )
    @cmd = aCmd.to_cmd
    @runner = Commands::Runners::System.new
    @h = HighLine.new
    self.cmd_data_factory = VcsCmdDataFactory.new(:output => STDOUT, :error => STDERR)

    unless is_a? Cvs
      @runner.subscribe_hook(:failure) do |command, data|
        data = command if data.nil? # Backward compatiblity
        logger.error { 'command: ' + command.to_s.gsub('"', '') }
        logger.error { "exit: #{data.status.exitstatus}" }
        suppress(IOError) do
          o = data.output.read
          logger.error { o.gsub!(/^/, 'stdout: ') ; o } unless o.empty?
        end
        suppress(IOError) do
          o = data.error.read
          logger.error { o.gsub!(/^/, 'stderr: ') ; o } unless o.empty?
        end
        # logger.error { 'data: ' + data.to_yaml }
        if data.output == STDOUT
          exit((data.status)? data.status.exitstatus : 1)
        else
          raise 'command failed'
        end
      end
    end
    @runner.subscribe_hook(:display_command) do |cmd|
      logger.debug { "running: #{cmd.to_sh}" }
    end
    @runner.subscribe_hook(:before_exec) do
      STDOUT.flush
      STDERR.flush
    end
  end

[Source]

# File lib/vcs/environment.rb, line 18
    def pager
      env('PAGER').to_cmd
    end

Here we can handle version conflicts with vcs extensions

[Source]

# File lib/vcs/vcs.rb, line 720
    def protocol_version ( aVersion )
      if aVersion != '0.1'
        raise ArgumentError, "Bad protocol version #{aVersion} but 0.1 is needed"
      end
    end

[Source]

# File lib/vcs/vcs.rb, line 707
    def regex_list
      @@regex_list ||= RegexList.new(user_conf.sorting)
    end

[Source]

# File lib/vcs/vcs.rb, line 669
    def user_conf_match ( sym, file )
      if user_conf.nil? or (regexps = user_conf.send(sym)).nil?
        return false
      end
      regexps.each do |re|
        return true if re.match(file) or re.match(file.basename)
      end
      return false
    end

[Source]

# File lib/vcs/vcs.rb, line 703
    def xmas_tree_colors?
      Vcs.user_conf.color == :xmas_tree
    end

Public Instance methods

[Source]

# File lib/vcs/add.rb, line 10
  def add! ( files=[], options={} )
    if options[:auto]
      options.delete(:auto)
      list!(files, :unrecognize => true) do |path_list|
        add_!(path_list.stringify, options) unless path_list.empty?
      end
    else
      add_!(files, options)
    end
  end

This command take a command as argument and search the last revision where this command success.

Example:

  * this dummy example success only if the revision is equal to 0 modulo X
  * replace X by the success revision and Y by a greater revision

vcs-svn back -r Y vcs-svn script ‘exit(rev.read.to_i % X)’

[Source]

# File lib/vcs/back.rb, line 14
  def back! ( files=[], options={} )
    sub_vcs = sub_vcs_with_name('checkout-4-vcs-back')
    dir = TempPath.new('checkout-dir-4-vcs-back')
    cmd = files.to_cmd
    cmd.dir = dir
    rev = options[:revision] || revision.read.chomp
    raise ArgumentError, "Just integers are supported for revisions" if rev !~ /^\d+$/
    rev = rev.to_i
    target_url = url.read.chomp
    while not rev.zero?
      sub_vcs.checkout([target_url, dir], :quiet => true, :revision => rev)
      data = cmd.system
      data.display if options[:verbose]
      if data.status.success?
        logger.info { "Your command success on revision #{rev}"}
        break
      else
        logger.warn { "Your command fail on revision #{rev}" }
      end
      rev -= 1
    end
  end

[Source]

# File lib/vcs/vcs.rb, line 659
  def call_conf_checkers
    @@checkers.each { |x| (x.is_a? Proc)? x[] : send(x) }
  end

[Source]

# File lib/vcs/vcs.rb, line 655
  def call_handlers
    @@handlers.each { |k, v| (v.arity.abs == 1)? v[k] : v[] }
  end

[Source]

# File lib/vcs/diffstat.rb, line 19
  def check_diffstat
    unless `diffstat -V` =~ /diffstat version/
      raise ArgumentError, 'diffstat: diffstat is required'
    end
  end

[Source]

# File lib/vcs/environment.rb, line 52
  def check_env
    %w[ email fullname editor pager ].each { |m| Vcs.send(m) }
  end

[Source]

# File lib/vcs/diff.rb, line 12
  def check_gnu_diff
    unless `diff --version` =~ /GNU/
      raise ArgumentError, 'diffw: Gnu diff is required'
    end
  end

[Source]

# File lib/vcs/vcs.rb, line 395
  def cmd_data_factory
    @runner.command_data_factory
  end

[Source]

# File lib/vcs/vcs.rb, line 399
  def cmd_data_factory= ( aFactory )
    @runner.command_data_factory = aFactory
    @cmd_data = aFactory.new_command_data
  end

[Source]

# File lib/vcs/vcs.rb, line 584
  def color ( aString, *someStyles )
    if color?
      @h.color(aString, *someStyles)
    else
      aString
    end
  end

[Source]

# File lib/vcs/vcs.rb, line 580
  def color?
    Vcs.color? { output.tty? }
  end

[Source]

# File lib/vcs/status.rb, line 59
  def color_status! ( *args )
    status(*args) do |status_entry|
      status_entry.colorize!
      puts status_entry.line
    end
  end

[Source]

# File lib/vcs/common_commit.rb, line 132
  def commit_failed ( ex=nil )
    Message.unlink if defined? Message and Message.exist? and not committed?
    logger.error { "Aborting #{ex}" }
    logger.info { 'You can rerun the same command to resume the commit' }
    raise 'Commit failed'
  end

[Source]

# File lib/vcs/common_commit.rb, line 139
  def committed?
    Vcs.commit_state.is_a? Integer
  end

[Source]

# File lib/vcs/common_commit.rb, line 151
  def committing?
    [:editing, :committing, :sending].include? Vcs.commit_state
  end

Same switches as mk_changelog_entry

[Source]

# File lib/vcs/changelog.rb, line 98
  def concat_changelog! ( *args )
    error_handling :concat_changelog_failed

    unless TMP_CL.exist?
      logger.info "Backup your `#{CL}' to `#{TMP_CL}' ..."
      CL.rename(TMP_CL)
    end

    CL.open('w') do |file|
      logger.info "#{CL}: Writing your new entry ..."
      with(file).mk_changelog_entry!(*args)
      file.puts
      logger.info "#{CL}: Writing the others ..."
      file.print TMP_CL.read
    end
  end

[Source]

# File lib/vcs/changelog.rb, line 116
  def concat_changelog_failed
    if TMP_CL.exist?
      logger.info "Restoring `#{CL}' from `#{TMP_CL}' ..."
      TMP_CL.rename(CL)
    end
  end

[Source]

# File lib/vcs/delete.rb, line 10
  def delete! ( files=[], options={} )
    if options[:auto]
      options.delete(:auto)
      list!(files, :missing => true) do |path_list|
        delete_!(path_list.stringify, options) unless path_list.empty?
      end
    else
      delete_!(files, options)
    end
  end

Use the diffstat command to display statitics on your patch.

[Source]

# File lib/vcs/diffstat.rb, line 13
  def diffstat! ( *a )
    check_diffstat
    (diffw(*a) | @@diffstat).run(@runner)
  end

[Source]

# File lib/vcs/diff.rb, line 8
  def diffw! ( *args )
    diff_!(*args)
  end

[Source]

# File lib/vcs/diff.rb, line 19
  def diffw_base ( files_orig=[], options={} )
    files = []
    status(files_orig, just_standard_options(options)) do |se|
      next if se.file_st.chr =~ /[?X\\,+D]/
      next if se.file.to_s == 'ChangeLog'
      next if se.file.directory?
      files << se.file unless files.include? se.file
    end
    files
  end

[Source]

# File lib/vcs/edit.rb, line 10
  def edit! ( files=[], options={} )
    cmd = Vcs.editor + files > [STDOUT, STDERR]
    cmd.run(@runner)
  end

[Source]

# File lib/vcs/conflict.rb, line 18
  def edit_conflicts! ( files=[], options={} )
    edit! mk_conflicts_list(files, options)
    resolve_conflicts! files, options
  end

[Source]

# File lib/vcs/form.rb, line 8
  def edit_form! ( *args )
    mk_form(*args)
    edit! Form
    mk_iform(*args)
    return YAML.load(IForm.read)['Revision'] || :committing
  end

[Source]

# File lib/vcs/common_commit.rb, line 143
  def editing?
    Vcs.commit_state == :editing
  end

[Source]

# File lib/vcs/vcs.rb, line 651
  def error_handling ( meth_or_path, &block )
    @@handlers[meth_or_path] = (block.nil?)? method(meth_or_path) : block
  end

[Source]

# File lib/vcs/vcs.rb, line 451
  def flush
    output.flush
  end

[Source]

# File lib/vcs/vcs.rb, line 550
  def help! ( files=[], options={} )
    return help_!(files, options) unless files.empty? and options.empty?
    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 = []
    public_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(', ')
        puts "  - #{cmd} (alias #{aliases})"
      else
        puts "  - #{cmd}"
      end
    end
  end

This command removes all junk files (by default all files begining with `,’). Warning: this command removes some files that may contains some important information. For example during a commit the information that you type is stored in one of these `,files’. So be careful using this command. See the user configuration to customize what is considered a junk file.

[Source]

# File lib/vcs/junk.rb, line 14
  def junk! ( files=[], options={} )
    list!(files, options.merge(:junk => true)) do |path_list|
      path_list.each { |path| logger.info { "Remove #{path}" } }
      if @h.agree('Are you sure? (y/n)', true)
        path_list.each do |path|
          logger.info { "Removing #{path}..." }
          path.rm_f
        end
      end
    end
  end

[Source]

# File lib/vcs/vcs.rb, line 596
  def just_standard_options ( options )
    result = {}
    options.each do |k, v|
      result[k] = v if standard_option? k
    end
    result
  end

[Source]

# File lib/vcs/last_changed_date.rb, line 8
  def last_changed_date! ( *args )
    puts info(*args).read[/^Last Changed Date:.*?\(([^)]*)\).*$/, 1]
  end

Mail.

FIXME handle options properly. Delegate the option parsing to Sendmail.

[Source]

# File lib/vcs/mail.rb, line 24
  def mail! ( files=[], options={} )
    # Backward compatiblity
    files, options = [], files if files.is_a? Hash or files.is_a? OpenStruct
    options = @@default_options.merge(options)
    options[:signed] = Vcs.user_conf.sign
    options = @@mailer.parse_mail_options(options)
    if editing?
      Vcs.mail_options = options
      return
    end
    header = YAML.load(IForm.read)
    %w[ Log ChangeLog YamlLog Message Title ].each { |x| header.delete x }
    options.to = header['To']
    from = header['From']
    options.from = from[/<(.*)>/, 1] || from
    options.header.merge! header
    options.header.symbolize_keys!
    return if header['To'].nil?
    rev = header['Revision']
    unless MAIL.exist?
      print_body(MAIL, options, files)
    end
    if sending?
      mail = MAIL.read.gsub(/<%= rev %>/, rev.to_s)
      MAIL.open('w') { |f| f.puts mail }
      @@mailer.sendmail
      puts 'Mail: Sent.'
    end
  end

[Source]

# File lib/vcs/mail.rb, line 56
  def mail_conf_checker
    if Vcs.user_conf.sign
      unless `gpg --version` =~ /^gpg \(GnuPG\)/
        logger.error 'mail: gunpg is required'
      end
      unless File.exist?("#{ENV['HOME']}/.gnupg/secring.gpg")
        logger.error 'no private key: in your ~/.gnupg'
      end
    end
  end

[Source]

# File lib/vcs/vcs.rb, line 496
  def method_missing ( meth, *args )
    meth = meth.to_s
    if meth =~ /^(.*)!$/
      no_bang = $1
      if respond_to? no_bang
        puts send(no_bang, *args)
      else
        run_missing!(no_bang, meth, *args)
      end
    else
      with_bang = meth + '!'
      return run_missing!(meth, meth, *args) unless respond_to? with_bang
      copy = sub_vcs_with_name(meth)
      copy.send(with_bang, *args)
      out = copy.cmd_data
      out.out_io.close
      out
    end
  end

Same switches as mk_log_entry

[Source]

# File lib/vcs/changelog.rb, line 77
  def mk_changelog_entry! ( *args )
      puts Time.now.strftime("%Y-%m-%d  #{Vcs.full_email}")
      puts
      mk_log_entry(*args).each_line(&method(:log_to_changelog))
  end

[Source]

# File lib/vcs/form.rb, line 61
  def mk_form! ( files=[], options={} )
    with_cache! Form, 'complete form (title, subject, ChangeLog entry, diff)' do

      puts "
      |--You must fill this file correctly to continue--#{' '*13}-*- vcs -*-
      |Title: \"\"
      |Subject: #{@@subject_format.dump}
      |From: \"#{Vcs.full_email}\"
      |To: [#{options[:to].join(', ')}]
      |".head_cut!

      options = just_standard_options options

      case Vcs.user_conf.log_mode.to_sym
      when :change_log
        puts "
        |ChangeLog:
        |".head_cut!
        mk_log_entry(files, options).each_line(&method(:log_to_changelog))
      when :log
        puts "
        |Log: |2
        |".head_cut!
        mk_log_entry(files, options).each_line { |line| puts "  #{line}" }
      when :yaml_log
        puts "
        |YamlLog:
        |".head_cut!
        mk_yaml_log_entry!(files, options)
      end
      puts "
      |#{@@message_line}
      |
      |#{@@last_line}
      |".head_cut!

      if Vcs.user_conf.new_user
        puts "|
        |Instructions:
        |- Fill the changelog/log entry.
        |- The first line must be removed when this file is filled.
        |- After you must specify a title, for the news/mail subject.
        |  The tag <%= Title %> will be automatically replaced by your title,
        |  <%= Subject %> by the subject line, <%= Rev %> by the revision...
        |- Everywhere in the document you can get/compute some values with
        |  these tags <%= aRubyExpression %> even some vcs specific call.
        |  For example <%= status.read %> will include the 'svn status' output.
        |- The Title will be automatically added on the top of your ChangeLog
        |  entry. The line with the date and your name will be added too.
        |
        |".head_cut!
        case Vcs.user_conf.log_mode.to_sym
        when :log
          puts "- Tabulations and stars ('*') will be added in the ChangeLog before each line."
        end
      end

      mk_message!(files, options)
      Message.unlink
    end
  end

[Source]

# File lib/vcs/form.rb, line 17
  def mk_iform! ( *args )
    with_cache! IForm, 'instanciated form' do
      form = mk_form(*args).read

      # Remove the first info line if present
      form.gsub!(/\A--.*\n/, '')

      # Get the message between the `message line' and the `last line'
      message = form[/^#{@@message_line}$(.*)^#{@@last_line}$/m, 1]

      # Remove every thing after the `message line'
      form.gsub!(/^#{@@message_line}$.*\Z/m, '')

      # Handle ChangeLog entries to make it Yaml compliant
      form.gsub!(/^(ChangeLog:)$/, '\1 |2')
      form.gsub!(/^\t/, "  \t")
      form.gsub!(/^ {8}/, "  \t")

      header = YAML.load(form)

      input = header['Log'] || header['ChangeLog']

      if header['Title'].nil? or header['Title'].blank?
        raise Failure, "No title found. Reopen `#{Form}' and add it"
      end
      header['Title'] += '.' unless header['Title'] =~ /[.?!]$/
      rev = '<%= rev %>' # make the revision substitution afterward
      b = getBinding(header.merge(:rev => rev, :revision => rev))
      input = ERB.new(input, nil, '<-%->', '$erbout_').result(b)
      LogEntry.open('w') { |f| f.print input }
      header['Message'] = message
      header.each_value do |v|
        next unless v.is_a? String
        v.replace(ERB.new(v, nil, '<-%->', '$erbout_').result(b))
      end
      puts header.to_yaml
    end
  end

Same switches as status

[Source]

# File lib/vcs/changelog.rb, line 40
  def mk_log_entry! ( *args )
    with_cache! LogEntry, 'Log entry' do
      puts '<%= Title %>'
      puts
      mk_log_entry_contents(*args).each do |se|
        puts "- #{se.file}: #{se.comment}."
      end
    end
  end

[Source]

# File lib/vcs/message.rb, line 22
  def mk_message! ( files=[], options={} )
    with_cache! Message, 'generated message (ChangeLog, diffstat, diff)' do
      url!
      if msg = options['Message']
        puts msg
      end
      options = just_standard_options options
      if defined? COLLABOA
        puts 'You can also view this changeset here:'
        puts
        puts "http://#{COLLABOA}/repository/changesets/<%= rev %>"
      end
      puts
      flush
      mk_message_entry!(files, options)
      puts
      flush
      diffstat!(files, options)
      puts
      flush
      diffw(files, options).each_line do |line|
        print line if line !~ /^=+$/
      end
    end
  end

Same switches as mk_log_entry

[Source]

# File lib/vcs/changelog.rb, line 86
  def mk_message_entry! ( *args )
      puts 'Index: ChangeLog'
      puts "from  #{Vcs.full_email}"
      puts
      puts "\tDo not fill this draft entry!" if editing?
      mk_log_entry(*args).each_line(&method(:log_to_changelog))
  end

Same switches as status

[Source]

# File lib/vcs/changelog.rb, line 54
  def mk_yaml_log_entry! ( *args )
    raise NotImplentedError
    # with_cache! LogEntry, 'Log entry' do
      # mk_log_entry_contents(*args).each do |se|
        # puts "  - #{se.file}: >2\n    #{se.comment}."
      # end
    # end
  end

Post the news.

[Source]

# File lib/vcs/news.rb, line 61
  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
      logger.info('news') { "Nntp Server: #{server}:#{port}" }
      unless @h.agree("Post a news, with this subject: #{opt[:subject]}\n" +
             "  to #{opt[:groups].join(', ')}\n  from #{opt[:from]}\n" +
             'Are you sure? (y/n)', true)
        logger.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
    puts @news_status
  end

[Source]

# File lib/vcs/news.rb, line 107
  def news_conf_checker
    %w[ NNTPSERVER ].each do |var|
      if ENV[var].nil? or ENV[var].empty?
        logger.error "environment variable `#{var}' not set"
      end
    end
  end

[Source]

# File lib/vcs/news.rb, line 100
  def news_failed
    if defined? NEWS and NEWS.exist?
      logger.info "#{NEWS}: Contains the generated news" +
               "(generated from #{@@message})"
    end
  end

[Source]

# File lib/vcs/vcs.rb, line 447
  def output
    @cmd_data.out_io
  end

[Source]

# File lib/vcs/edit.rb, line 15
  def paginate! ( files=[], options={} )
    cmd = Vcs.pager + files > [STDOUT, STDERR]
    cmd.run(@runner)
  end

[Source]

# File lib/vcs/conflict.rb, line 23
  def resolve_conflicts! ( files=[], options={} )
    conflicts = mk_conflicts_list(files, options)
    question = "Resolve these conflicts?: \n  - #{conflicts.join("\n  - ")}\n(y/n)"
    if @h.agree question, true
      return resolved(conflicts)
    end
  end

[Source]

# File lib/vcs/vcs.rb, line 455
  def run ( *args )
    sub_vcs.run!(*args)
  end

[Source]

# File lib/vcs/vcs.rb, line 421
  def run! ( command, files=[], options={} )
    flush
    pre_cmd_options, cmd_options = option_controller.to_strings(options)
    (@cmd + pre_cmd_options + command + cmd_options + '--' + files).run(@runner)
  end

[Source]

# File lib/vcs/vcs.rb, line 471
  def run_argv ( argv )
    options, files = option_controller.parse(argv)
    if options[:help]
      meth = :help!
      options.delete(:help)
    elsif files.empty?
      if options[:version]
        meth = '--version'
        options.delete(:version)
      else
        options.delete(:help)
        meth = :help!
      end
    else
      meth = files.shift.dup
      meth.sub!(/([^!])$/, '\1!') if meth != 'script'
    end
    logger.debug { "meth: #{meth}, files: #{files.inspect}, options: #{options.inspect}" }
    send(meth, files, options)
  end

[Source]

# File lib/vcs/script.rb, line 10
  def script ( files=[], options={} )
    puts script!(files, options)
  end

[Source]

# File lib/vcs/script.rb, line 14
  def script! ( files=[], options={} )
    begin
      eval(files.join(' '))
    rescue SystemExit => ex
      raise ex
    rescue Exception => ex
      logger.error { 'Vcs#script: during the client execution' }
      logger.error { ex.long_pp }
    end
  end

[Source]

# File lib/vcs/common_commit.rb, line 147
  def sending?
    Vcs.commit_state == :sending
  end

[Source]

# File lib/vcs/status.rb, line 76
  def spawn_status_entries ( status_data, &block )
    result = PathList.new
    status_data.each_line do |line|
      next unless line =~ /^.{5} /
      status_entry = StatusEntry.new(@h, line)
      next if status_entry.category == :exclude
      result << status_entry
    end
    result.sort_with_regex_list! Vcs.regex_list
    result.each(&block)
  end

[Source]

# File lib/vcs/vcs.rb, line 592
  def standard_option? ( option_name )
    false
  end

[Source]

# File lib/vcs/status.rb, line 66
  def status! ( *args )
    if color?
      color_status!(*args)
    else
      status(*args) do |status_entry|
        puts status_entry.line
      end
    end
  end

[Source]

# File lib/vcs/vcs.rb, line 427
  def sub_vcs ( out, err, vcs_class=nil, &block )
    copy = (vcs_class || self.class).new(@cmd)
    copy.cmd_data_factory = VcsCmdDataFactory.new(:output => out, :error => err)
    if block.nil?
      copy
    else
      copy.instance_eval(&block)
    end
  end

[Source]

# File lib/vcs/vcs.rb, line 437
  def sub_vcs_with_name ( name, vcs_class=nil, &block )
    sub_vcs(TempPath.new("#{name}-out"), TempPath.new("#{name}-err"),
            vcs_class, &block)
  end

[Source]

# File lib/vcs/url.rb, line 8
  def url! ( *args )
    puts info(*args).read[/^URL:\s+(.*)$/, 1]
  end

[Source]

# File lib/vcs/vcs.rb, line 442
  def with ( io, vcs_class=nil, &block )
    io.flush if io.respond_to? :flush
    sub_vcs(io, io, vcs_class, &block)
  end

Protected Instance methods

[Source]

# File lib/vcs/common_commit.rb, line 10
  def common_commit! ( subject_format, files=[], commit_opts={}, &block )

    unless CL.exist?
      raise Failure, "No `#{CL}', you are probably not in a valid directory."
    end

    Vcs.commit_state = :editing
    force = commit_opts[:force]
    commit_opts.delete :force

    opts = just_standard_options commit_opts

    @@subject_format = subject_format

    logger.info { 'Updating your working copy...' }
    update! [], opts

    have_unrecognized_files = false
    status(files, opts) do |se|
      if se.category == :unrecognize
        have_unrecognized_files = true
        se.colorize! if color?
        puts se.line
      end
    end
    if have_unrecognized_files
      message = 'You have unrecognized files in your working copy!'
      if Vcs.user_conf.new_user
        message << "
          |This meant that these files won't be committed!
          |You have some solutions to comply with the rule:
          |- You must put these files in some categories.
          |    For instance you can rename these files and put a `+' before
          |    to make it `precious':
          |      put `,' for `junk'
          |      put `\\' for `unmask'
          |      put `-' for `exclude'
          |- You can also edit your configuration file (.vcs) to customize
          |    these categories. For example add this:
          |    ------------ .vcs ------------
          |    precious:
          |      - !re my_precious_file[0-9]*
          |      - !re .*\.patch
          |    ------------ .vcs ------------
          |- You can also perform a partial commit and specify which files
          |    and directories commit. For example this command:
          |    #{@cmd.command} commit foo.c bar/
          |
          |".head_cut!
      end
      if force
        logger.warn { message }
      else
        logger.error { message }
        commit_failed
      end
    end

    block['empty subject'] if block_given?

    Vcs.commit_state = edit_form!(files, opts.merge(:to => Vcs.mail_options.to))

    iform = YAML.load(IForm.read)

    Message.unlink if Message.exist? and not committed?
    mk_message(files, opts.merge(iform))
    block[iform['Subject']] if block_given?
    paginate! Message

    unless committed?

      if Vcs.interactive?
        question = 'Committing, are you sure?'
        begin
          response = @h.agree "#{question} (y/n)", true
        rescue NoMethodError
          response = @h.agree "#{question} (yes/no)"
        end
        unless response
          commit_failed
        end
      end

      concat_changelog!(files, opts)

      files << 'ChangeLog' unless files.empty?

      begin
        commit_!(files, commit_opts.merge(:message => mk_log_entry(files).read))
        update!
        revision = rev.read.to_i
        iform = YAML.load(IForm.read).merge('Revision' => revision)
        IForm.open('w') { |f| f.print iform.to_yaml }
        Vcs.commit_state = revision
        TMP_CL.delete if TMP_CL.exist?
      rescue Exception => ex
        commit_failed ex
      end

    end

    Vcs.commit_state = :sending
    block[iform['Subject']] if block_given?

    logger.info { 'Deleting junk files...' }
    TMP_CL.delete if TMP_CL.exist?
    # Backward typo compatibility
    '+commited'.to_path.mv('+committed') if '+commited'.to_path.exist?
    destdir = '+committed'.to_path/iform['Revision'].to_s
    destdir.mkpath unless destdir.directory?
    moved = PathList.new
    [LogEntry, Form, IForm, Message].each do |path|
      next unless path.exist?
      dest = destdir/path
      moved << path
      path.rename(dest)
    end
    logger.info { "Moving `#{moved.join('\', `')}' to `#{destdir}'..." }

  end

[Source]

# File lib/vcs/form.rb, line 125
  def getBinding ( header )
    code = ['module GetBinding']
    header.each do |k, v|
      code << "#{k.to_s.capitalize} = #{v.inspect}"
      code << "#{k.to_s.downcase} = #{v.inspect}"
    end
    code << 'binding' << 'end'
    eval(code.join('; '))
  end

[Source]

# File lib/vcs/conflict.rb, line 8
  def mk_conflicts_list ( files=[], options={} )
    conflicts = []
    status(files, options) do |se|
      conflicts << se.file if se.category == :conflict
    end
    raise "no conflicts" if conflicts.empty?
    conflicts
  end

[Source]

# File lib/vcs/news.rb, line 14
  def parse_news_options ( *args )
    require 'optparse'
    result =
    {
      :from => Vcs.full_email,
      :groups => [],
      :server => Vcs.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

[Source]

# File lib/vcs/vcs.rb, line 459
  def run_missing! ( name, orig, *args )
    if name =~ /^(.*)_$/
      run!($1, *args)
    elsif name =~ /^--/
      run!(name, *args)
    else
      logger.warn { "Unknown command: '#{orig.gsub('!', '')}'" }
      run!(name, *args)
    end
  end

[Source]

# File lib/vcs/vcs.rb, line 518
  def with_cache ( path=nil, description=nil, &block )
    loc = block.source_location # FIXME verify that this type of cache is working
    return @@cache[loc].dup if @@cache.has_key? loc
    unless path.nil?
      if description.nil?
        raise ArgumentError, "need a description for #{path}"
      end
      error_handling(path) do
        logger.info "#{path}: Contains your #{description}" if path.exist?
      end
    end
    if path.exist?
      logger.info "#{path} already exists"
      return path.read
    end
    begin
      logger.info "Creating a new `#{path}' file..."
      path.open('w') { |f| result = with(f, &block) }
    rescue Exception => ex
      logger.error "Removing `#{path}'..."
      path.unlink
      raise ex
    end
    path.read
  end

[Source]

# File lib/vcs/vcs.rb, line 545
  def with_cache! ( *a, &b )
    puts with_cache(*a, &b)
  end

[Validate]