class OhlohScm::Cvs::Scm

Public Instance Methods

checkout(rev, local_directory) click to toggle source

rubocop:disable Metrics/AbcSize, Metrics/MethodLength rubocop:disable Metrics/PerceivedComplexity

# File lib/ohloh_scm/cvs/scm.rb, line 8
def checkout(rev, local_directory)
  opt_d = rev.token ? "-D'#{rev.token}Z'" : ''

  activity.ensure_host_key
  if File.exist?(local_directory + '/CVS/Root')
    # We already have a local enlistment, so do a quick update.
    if !rev.directories.empty?
      build_ordered_directory_list(rev.directories).each do |d|
        if d.empty?
          run "cd #{local_directory} && cvsnt update -d -l -C #{opt_d} ."
        else
          run "cd #{local_directory} && cvsnt update -d -l -C #{opt_d} '#{d}'"
        end
      end
    else
      # Brute force: get all updates
      logger.warn("Revision #{rev.token} did not contain any directories.
      Using brute force update of entire module.")
      run "cd #{local_directory} && cvsnt update -d -R -C #{opt_d}"
    end
  else
    # We do not have a local enlistment, so do a slow checkout to create one.
    # Silly cvsnt won't accept an absolute path.
    # We'll have to play some games and cd to the parent directory.
    parent_path, checkout_dir = File.split(local_directory)
    FileUtils.mkdir_p(parent_path) unless File.exist?(parent_path)
    run "cd #{parent_path} &&
    cvsnt -d #{url} checkout #{opt_d} -A -d'#{checkout_dir}' '#{branch_name}'"
  end
end
normalize() click to toggle source

rubocop:enable Metrics/AbcSize, Metrics/MethodLength rubocop:enable Metrics/PerceivedComplexity

# File lib/ohloh_scm/cvs/scm.rb, line 41
def normalize
  # Some CVS forges publish an URL which is actually a symlink, which causes CVSNT to crash.
  # For some forges, we can work around this by using an alternate directory.
  case guess_forge
  when 'java.net', 'netbeans.org'
    url.gsub!(/:\/cvs\/?$/, ':/shared/data/ccvs/repository')
  when 'gna.org'
    url.gsub!(/:\/cvs\b/, ':/var/cvs')
  end

  sync_pserver_username_password

  self
end

Private Instance Methods

build_ordered_directory_list(directories) click to toggle source

A revision can contain an arbitrary collection of directories. We need to ensure that for every directory we want to fetch, we also have its parent directories. rubocop:disable Metrics/AbcSize, Metrics/MethodLength rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity

# File lib/ohloh_scm/cvs/scm.rb, line 63
def build_ordered_directory_list(directories)
  # Integration Test Limitation
  # cvsnt has problems with absolute path names, so we are stuck with
  # using cvs modules that are only a single directory deep when testing.
  # We'll check if the url begins with '/' to detect an integration test,
  # then return an empty string (ie, the default root directory) if so.
  return [''] if url =~ /^\//

  list = []
  directories = directories.collect { |a| trim_directory(a.to_s).to_s }
  directories.each do |d|
    # We always ignore Attic directories, which just contain deleted files
    # Update the parent directory of the Attic instead.
    if d =~ /^(.*)Attic$/
      d = Regexp.last_match(1)
      d = d[0..-2] if !d.empty? && (d[-1, 1] == '/')
    end

    next if list.include? d

    list << d
    # We also need to include every parent directory of the directory
    # we are interested in, all the way up to the root.
    while d.rindex('/')&.positive?
      d = File.dirname(d)
      break if list.include? d

      list << d
    end
  end

  # Sort the list by length because we need to update parent directories before children
  list.sort! { |a, b| a.length <=> b.length }
end
guess_forge() click to toggle source

Based on the URL, take a guess about which forge this code is hosted on.

# File lib/ohloh_scm/cvs/scm.rb, line 142
def guess_forge
  return unless url =~ /.*(pserver|ext).*@(([^\.]+\.)?(cvs|dev)\.)?([^:]+):\//i

  Regexp.last_match(5).downcase
end
root() click to toggle source
# File lib/ohloh_scm/cvs/scm.rb, line 111
def root
  return unless url =~ /^:(pserver|ext):.*@[^:]+:(\d+)?(\/.*)$/

  "#{Regexp.last_match(3)}/#{branch_name}/"
end
sync_pserver_username_password() click to toggle source

This bit of code patches up any inconsistencies that may arise because there is both a @password attribute and a password embedded in the :pserver: url. This method guarantees that they are both the same.

It's assumed that if the user specified a @password attribute, then that is the preferred value and it should take precedence over any password found in the :pserver: url.

If the user did not specify a @password attribute, then the value found in the :pserver: url is assigned to both.

# File lib/ohloh_scm/cvs/scm.rb, line 127
def sync_pserver_username_password
  # Do nothing unless pserver connection string is well-formed.
  return unless url =~ /:pserver:([\w\-\_]*)(:([\w\-\_]*))?@(.*)$/

  pserver_username = Regexp.last_match(1)
  pserver_password = Regexp.last_match(3)
  pserver_remainder = Regexp.last_match(4)

  @username = pserver_username if @username.to_s.empty?
  @password = pserver_password if @password.to_s.empty?

  @url = ":pserver:#{@username}:#{password}@#{pserver_remainder}"
end
trim_directory(dir) click to toggle source

rubocop:enable Metrics/AbcSize, Metrics/MethodLength rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity

# File lib/ohloh_scm/cvs/scm.rb, line 100
def trim_directory(dir)
  # If we are connecting to a remote server (basically anytime we are not
  # running the integration test) then we need to create a relative path
  # by trimming the prefix from the directory.
  # The prefix can be determined by examining the url and the module name.
  # For example, if url = ':pserver:anonymous:@moodle.cvs.sourceforge.net:/cvsroot/moodle'
  # and module = 'contrib', then the directory prefix = '/cvsroot/moodle/contrib/'
  # If not remote, just leave the directory name as-is
  root ? dir[root.length..-1] : dir
end