class Autobuild::SVN

Attributes

revision[R]
svnroot[R]

Returns the SVN root

@return [String]

Public Class Methods

new(svnroot, options = {}) click to toggle source

Creates an importer which gets the source for the Subversion URL source. The following options are allowed:

:svnup

options to give to 'svn up'

:svnco

options to give to 'svn co'

This importer uses the 'svn' tool to perform the import. It defaults to 'svn' and can be configured by doing

Autobuild.programs['svn'] = 'my_svn_tool'
Calls superclass method
# File lib/autobuild/import/svn.rb, line 15
def initialize(svnroot, options = {})
    svnroot = [*svnroot].join("/")
    svnopts, common = Kernel.filter_options(
        options,
        :svnup => [], :svnco => [], :revision => nil,
        :repository_id => "svn:#{svnroot}"
    )
    common[:repository_id] = svnopts.delete(:repository_id)
    relocate(svnroot, svnopts)
    super(common.merge(repository_id: svnopts[:repository_id]))
end

Public Instance Methods

has_local_modifications?(package, with_untracked_files = false) click to toggle source

Returns true if the SVN working copy at package.importdir has local modifications

@param [Package] package the package we want to test against @param [Boolean] with_untracked_files if true, the presence of files

neither ignored nor under version control will count has local
modification.

@return [Boolean]

# File lib/autobuild/import/svn.rb, line 114
def has_local_modifications?(package, with_untracked_files = false)
    status = run_svn(package, 'status', '--xml')

    not_modified = %w[external ignored none normal]
    not_modified << "unversioned" unless with_untracked_files

    REXML::Document.new(status.join("")).
        elements.enum_for(:each, '//wc-status').
        any? do |status_item|
            !not_modified.include?(status_item.attributes['item'].to_s)
        end
end
relocate(root, options = Hash.new) click to toggle source
# File lib/autobuild/import/svn.rb, line 48
def relocate(root, options = Hash.new)
    @svnroot = [*root].join("/")
    @options_up = [*options[:svnup]]
    @options_co = [*options[:svnco]]
    @revision = options[:revision]
    if revision
        @options_co << '--revision' << revision
        # We do not add it to @options_up as the behaviour depends on
        # the parameters given to {update} and to the state of the
        # working copy
    end
end
repository() click to toggle source

Alias for {#svnroot}

For consistency with the other importers

# File lib/autobuild/import/svn.rb, line 42
def repository
    svnroot
end
run_svn(package, *args, &block) click to toggle source

Helper method to run a SVN command on a package's working copy

# File lib/autobuild/import/svn.rb, line 164
def run_svn(package, *args, &block)
    options =
        if args.last.kind_of?(Hash)
            args.pop
        else
            Hash.new
        end

    options, other_options = Kernel.filter_options(
        options, working_directory: package.importdir, retry: true
    )
    options = options.merge(other_options)
    package.run(:import, Autobuild.tool(:svn), *args, options, &block)
end
source() click to toggle source

@deprecated use {svnroot} instead

@return [String]

# File lib/autobuild/import/svn.rb, line 30
def source
    svnroot
end
status(package, only_local = false) click to toggle source

Returns status information for package

Given that subversion is not a distributed VCS, the only status returned are either {Status::UP_TO_DATE} or {Status::SIMPLE_UPDATE}. Moreover, if the status is local-only, {Package::Status#remote_commits} will not be filled (querying the log requires accessing the SVN server)

@return [Package::Status]

# File lib/autobuild/import/svn.rb, line 136
def status(package, only_local = false)
    status = Status.new
    status.uncommitted_code = has_local_modifications?(package)
    if only_local
        status.status = Status::UP_TO_DATE
    else
        log = run_svn(package, 'log', '-r', 'BASE:HEAD', '--xml', '.')
        log = REXML::Document.new(log.join("\n"))
        missing_revisions = log.elements.enum_for(:each, 'log/logentry').
            map do |l|
                rev = l.attributes['revision']
                date = l.elements['date'].first.to_s
                author = l.elements['author'].first.to_s
                msg = l.elements['msg'].first.to_s.split("\n").first
                "#{rev} #{DateTime.parse(date)} #{author} #{msg}"
            end
        status.remote_commits = missing_revisions[1..-1]
        status.status =
            if missing_revisions.empty?
                Status::UP_TO_DATE
            else
                Status::SIMPLE_UPDATE
            end
    end
    status
end
svn_info(package) click to toggle source

Returns the result of the 'svn info' command

It automatically runs svn upgrade if needed

@param [Package] package @return [Array<String>] the lines returned by svn info, with the

trailing newline removed

@raises [SubcommandFailed] if svn info failed @raises [ConfigException] if the working copy is not a subversion

working copy
# File lib/autobuild/import/svn.rb, line 195
def svn_info(package)
    old_lang = ENV['LC_ALL']
    ENV['LC_ALL'] = 'C'
    begin
        svninfo = run_svn(package, 'info')
    rescue SubcommandFailed => e
        if e.output.find { |l| l =~ /svn upgrade/ }
            # Try svn upgrade and info again
            run_svn(package, 'upgrade', retry: false)
            svninfo = run_svn(package, 'info')
        else raise
        end
    end

    unless svninfo.grep(/is not a working copy/).empty?
        raise ConfigException.new(package, 'import'),
              "#{package.importdir} does not appear to be a "\
              "Subversion working copy"
    end
    svninfo
ensure
    ENV['LC_ALL'] = old_lang
end
svn_revision(package) click to toggle source

Returns the SVN revision of the package

@param [Package] package @return [Integer] @raises ConfigException if 'svn info' did not return a Revision field @raises (see svn_info)

# File lib/autobuild/import/svn.rb, line 67
def svn_revision(package)
    svninfo = svn_info(package)
    revision = svninfo.grep(/^Revision: /).first
    unless revision
        raise ConfigException.new(package, 'import'),
              "cannot get SVN information for #{package.importdir}"
    end
    revision =~ /Revision: (\d+)/
    Integer($1)
end
svn_url(package) click to toggle source

Returns the URL of the remote SVN repository

@param [Package] package @return [String] @raises ConfigException if 'svn info' did not return a URL field @raises (see svn_info)

# File lib/autobuild/import/svn.rb, line 95
def svn_url(package)
    svninfo = svn_info(package)
    url = svninfo.grep(/^URL: /).first
    unless url
        raise ConfigException.new(package, 'import'),
              "cannot get SVN information for #{package.importdir}"
    end
    url.chomp =~ /URL: (.+)/
    $1
end
validate_importdir(package) click to toggle source
# File lib/autobuild/import/svn.rb, line 179
def validate_importdir(package)
    # This upgrades the local SVN filesystem if needed and checks that
    # it actually is a SVN repository in the first place
    svn_info(package)
end
vcs_fingerprint(package) click to toggle source

fingerprint method returns an unique hash to identify this package, for SVN the revision and URL will be used @param [Package] package @return [String] @raises (see svn_info)

# File lib/autobuild/import/svn.rb, line 83
def vcs_fingerprint(package)
    Digest::SHA1.hexdigest(
        svn_info(package).grep(/^(URL|Revision):/).sort.join("\n")
    )
end