class Subtle::Sur::Client

  1. data/sur/client.rb
Superclass: Object

Client class for interaction with the user

Constants

BOUNDARY = "AaB03x"  

Header separator

HOST = "http://sur.subforge.org"  

Remote repository host

Attributes

cache_local [RW]

Local sublet cache

cache_remote [RW]

Remote sublet cache

path_icons [RW]

Path to icons

path_local [RW]

Path to local cache file

path_remote [RW]

Path to remote cache file

path_specs [RW]

Path of specification

path_sublets [RW]

Path to sublets

Public Class methods

new ()
Sur::Client::initialize {{{

Create a new Client object

@return [Object] New Client

@since 0.0

@example

client = Sur::Client.new
=> #<Sur::Client:xxx>
[show source]
# File data/sur/client.rb, line 64
def initialize
  # Paths
  xdg_cache_home = File.join((ENV["XDG_CACHE_HOME"] ||
    File.join(ENV["HOME"], ".cache")), "sur")
  xdg_data_home  = File.join((ENV["XDG_DATA_HOME"] ||
    File.join(ENV["HOME"], ".local", "share")), "subtle")

  @path_local   = File.join(xdg_cache_home, "local.yaml")
  @path_remote  = File.join(xdg_cache_home, "remote.yaml")
  @path_icons   = File.join(xdg_data_home,  "icons")
  @path_specs   = File.join(xdg_data_home,  "specifications")
  @path_sublets = File.join(xdg_data_home,  "sublets")

  # Create folders
  [ xdg_cache_home, xdg_data_home, @path_icons,
      @path_specs, @path_sublets ].each do |p|
    FileUtils.mkdir_p([ p ]) unless File.exist?(p)
  end
end

Public Instance methods

annotate (name, version = nil)
Sur::Client::annotate {{{

Mark a sublet as to be reviewed

@param [String] name Name of the Sublet @param [String] version Version of the Sublet

@raise [String] Annotate error @since 0.2

@example

Sur::Client.new.submit("sublet")
=> nil
[show source]
# File data/sur/client.rb, line 97
def annotate(name, version = nil)
  build_local
  build_remote

  # Check if sublet exists
  if (specs = search(name, @cache_remote, version, false)) and specs.empty?
    raise "Sublet `#{name}' does not exist"
  end

  spec = specs.first
  uri  = URI.parse(HOST + "/annotate")
  res  = Net::HTTP.post_form(uri,
    {
      "digest" => spec.digest,
      "user"   => ENV["USER"]
    }
  )

  raise "Cannot annotate sublet: Sublet not found" if 404 == res.code
end
build (file)
Sur::Client::build {{{

Build a sublet package

@param [String] file Spec file name

@see Sur::Specification.load_file @raise [String] Build error @since 0.1

@example

Sur::Client.new.build("sublet.spec")
=> nil
[show source]
# File data/sur/client.rb, line 131
def build(file)
  spec = Sur::Specification.load_spec(file)

  # Check specification
  if spec.valid?
    begin
      sublet = "%s-%s.sublet" % [
        File.join(Dir.pwd, spec.name.downcase),
        spec.version
      ]
      opts = { :mode => 644, :mtime => Time.now.to_i }

      # Check if files exist
      (spec.files | spec.icons).each do |f|
        unless File.exist?(File.join(File.dirname(file), f))
          raise "Cannot find file `#{f}'"
        end
      end

      # Check gem version
      unless spec.dependencies.empty?
        spec.dependencies.each do |name, version|
          if version.match(/^(\d*\.){1,2}\d*$/)
            puts ">>> WARNING: Gem dependency `%s' "                         "requires exact gem version (=%s)" % [ name, version ]
          end
        end
      end

      # Create tar file
      File.open(sublet, "wb") do |output|
        Archive::Tar::Minitar::Writer.open(output) do |tar|
          # Add Spec
          tar.add_file(File.basename(file), opts) do |os|
            os.write(IO.read(file))
          end

          # Add files
          spec.files.each do |f|
            tar.add_file(File.basename(f), opts) do |os|
              os.write(IO.read(File.join(File.dirname(file), f)))
            end
          end

          # Add icons
          spec.icons.each do |f|
            tar.add_file(File.basename(f), opts) do |os|
              os.write(IO.read(File.join(File.dirname(file), f)))
            end
          end
        end
      end

      puts ">>> Created sublet `#{File.basename(sublet)}'"
    rescue => error
      raise error.to_s
    end
  else
    spec.validate
  end
end
config (name, use_color = true)
Sur::Client::config {{{

Show config settings for installed sublets if any

@param [String] name Name of the Sublet @param [Bool] use_color Use colors

@raise [String] Config error @since 0.2

@example

Sur::Client.new.config("sublet")
=> "Name     Type    Default value Description"
   "interval integer 60            Update interval in seconds"
[show source]
# File data/sur/client.rb, line 207
def config(name, use_color = true)
  build_local

  # Check if sublet is installed
  if (specs = search(name, @cache_local)) and !specs.empty?
    spec = specs.first

    show_config(spec, use_color)
    see_also(spec)
  end
end
fetch (names, version = nil, use_tags = false)
Sur::Client::fetch {{{

Install a new Sublet

@param [Array] names Names of Sublets @param [String] version Version of the Sublet @param [String] use_tags Use tags

@raise [String] Fetch error @since 0.0

@example

Sur::Client.new.fetch([ "sublet" ])
=> nil
[show source]
# File data/sur/client.rb, line 233
def fetch(names, version = nil, use_tags = false)
  build_remote

  # Install all sublets
  names.each do |name|
    # Check if remote sublet exists
    if (specs = search(name, @cache_remote, version, use_tags)) and
        specs.empty?
      puts ">>> WARNING: Cannot find sublet `#{name}' "                   "in remote repository"

      next
    end

    spec = specs.first

    # Download and copy sublet to current directory
    unless (temp = download(spec)).nil?
      FileUtils.cp(temp.path,
        File.join(
          Dir.getwd,
          "%s-%s.sublet" % [ spec.name.downcase, spec.version ]
        )
      )
    end
  end
end
grabs (name, use_color = true)
Sur::Client::grabs {{{

Show grabs for installed sublets if any

@param [String] name Name of the Sublet @param [Bool] use_color Use colors

@raise [String] Config error @since 0.2

@example

Sur::Client.new.grabs("sublet")
=> "Name        Description"
   "SubletTest  Test grabs"
[show source]
# File data/sur/client.rb, line 275
def grabs(name, use_color = true)
  build_local

  # Check if sublet is installed
  if (specs = search(name, @cache_local)) and !specs.empty?
    spec = specs.first

    show_grabs(spec, use_color)
    see_also(spec)
  end
end
info (names, use_color = true)
Sur::Client::info {{{

Show info for installed sublets if any

@param [Array] names Names of the Sublets @param [Bool] use_color Use colors

@raise [String] Config error @since 0.2

@example

Sur::Client.new.info("sublet")
=> "Name        Description"
   "SubletTest  Test grabs"
[show source]
# File data/sur/client.rb, line 301
def info(names, use_color = true)
  build_local

  # Show info for all sublets
  names.each do |name|
    # Check if sublet is installed
    if (specs = search(name, @cache_local)) and !specs.empty?
      spec = specs.first

      show_info(spec, use_color)
      see_also(spec)
    end
  end
end
install (names, version = nil, use_tags = false, reload = false)
Sur::Client::install {{{

Install a new Sublet

@param [Array] names Names of Sublets @param [String] version Version of the Sublet @param [String] use_tags Use tags @param [Bool] reload Reload sublets after installing

@raise [String] Install error @since 0.0

@example

Sur::Client.new.install([ "sublet" ])
=> nil
[show source]
# File data/sur/client.rb, line 331
def install(names, version = nil, use_tags = false, reload = false)
  build_local
  build_remote

  # Install all sublets
  names.each do |name|
    # Check if sublet is already installed
    if (specs = search(name, @cache_local, version, use_tags)) and
        !specs.empty?
      puts ">>> WARNING: Sublet `#{name}' is already installed"

      next
    end

    # Check if sublet is local
    if File.exist?(name)
      install_sublet(name)

      next
    end

    # Check if remote sublet exists
    if (specs = search(name, @cache_remote, version, use_tags)) and
        specs.empty?
      puts ">>> WARNING: Cannot find sublet `#{name}' "                   "in remote repository"

      next
    end

    # Check dependencies
    spec = specs.first
    next unless spec.satisfied?

    # Download and install sublet
    unless (temp = download(spec)).nil?
      install_sublet(temp.path)
    end
  end

  build_local(true)

  reload_sublets if reload
end
list (repo, use_color = true)
Sur::Client::list {{{

List the Sublet in a repository

@param [String] repo Repo name @param [Bool] use_color Use colors

@since 0.0

@example

Sur::Client.new.list("remote")
=> nil
[show source]
# File data/sur/client.rb, line 388
def list(repo, use_color = true)
  # Select cache
  case repo
    when "local"
      build_local
      specs = @cache_local
    when "remote"
      build_local
      build_remote
      specs = @cache_remote
  end

  show_list(specs, use_color)
end
notes (name)
Sur::Client::notes {{{

Show notes about an installed sublet if any

@param [String] name Name of the Sublet

@raise [String] Notes error @since 0.2

@example

Sur::Client.new.notes("sublet")
=> "Notes"
[show source]
# File data/sur/client.rb, line 415
def notes(name)
  build_local

  # Check if sublet is installed
  if (specs = search(name, @cache_local)) and !specs.empty?
    spec = specs.first

    show_notes(spec)
    see_also(spec)
  end
end
query (query, repo, version = nil, use_regex = false, use_tags = false, use_color = true)
Sur::Client::query {{{

Query repo for a Sublet

@param [String] query Query string @param [String] repo Repo name @param [Bool] use_regex Use regex @param [Bool] use_tags Use tags @param [Bool] use_color Use colors

@raise [String] Query error @since 0.0

@example

Sur::Client.new.query("sublet", "remote")
=> nil
[show source]
# File data/sur/client.rb, line 443
def query(query, repo, version = nil, use_regex = false, use_tags = false, use_color = true)
  case repo
    when "local"
      build_local
      unless (specs = search(query, @cache_local, version,
          use_regex, use_tags)) and !specs.empty?
        raise "Cannot find `#{query}' in local repository"
      end
    when "remote"
      build_local
      build_remote
      unless (specs = search(query, @cache_remote, version,
          use_regex, use_tags)) and !specs.empty?
        raise "Cannot find `#{query}' in remote repository"
      end
  end

  show_list(specs, use_color)
end
reorder ()
Sur::Client::reorder {{{

Reorder install Sublet

@example

Sur::Client.new.reorder
=> nil
[show source]
# File data/sur/client.rb, line 470
def reorder
  build_local

  i     = 0
  list  = []
  files = Dir[@path_sublets + "/*"]

  # Show menu
  @cache_local.each do |s|
    puts "(%d) %s (%s)" % [ i + 1, s.name, s.version ]

    # Check for match if sublet was reordered
    files.each do |f|
      s.files.each do |sf|
        a = File.basename(f)
        b = File.basename(sf)

        if a == b or File.fnmatch("[0-9_]*#{b}", a)
          list.push([ s.name.downcase, a])
        end
      end
    end

    i += 1
  end

  # Get new order
  puts "\n>>> Enter new numbers separated by blanks:\n"
  printf ">>> "

  line = STDIN.readline
  i    = 0

  if "\n" != line
    line.split(" ").each do |tok|
      idx = tok.to_i

      name, file = list.at(idx -1)

      i        += 10
      new_path  = '%s/%d_%s.rb' % [ @path_sublets, i, name ]

      # Check if file exists before moving
      unless File.exist?(new_path)
        FileUtils.mv(File.join(@path_sublets, file), new_path)
      end
    end

    build_local(true) #< Update local cache
  end
end
submit (file)
Sur::Client::submit {{{

Submit a Sublet to a repository

@param [String] file Sublet package

@raise [String] Submit error @since 0.0

@example

Sur::Client.new.submit("sublet")
=> nil
[show source]
# File data/sur/client.rb, line 534
def submit(file)
  if !file.nil? and File.file?(file) and ".sublet" == File.extname(file)
    spec = Sur::Specification.extract_spec(file)

    if spec.valid?
      upload(file)
      build_remote(true)
    else
      spec.validate
    end
  else
    raise "Cannot find file `#{file}'"
  end
end
uninstall (names, version = nil, use_tags = false, reload = false)
Sur::Client::uninstall {{{

Uninstall a Sublet

@param [Array] names Names of Sublets @param [String] version Version of the Sublet @param [Bool] use_tags Use tags @param [Bool] reload Reload sublets after uninstalling

@raise [String] Uninstall error @since 0.0

@example

Sur::Client.new.uninstall("sublet")
=> nil
[show source]
# File data/sur/client.rb, line 564
def uninstall(names, version = nil, use_tags = false, reload = false)
  build_local

  # Install all sublets
  names.each do |name|
    # Check if sublet is installed
    if (specs = search(name, @cache_local, version, use_tags)) and
        !specs.empty?
      spec = specs.first

      # Uninstall files
      spec.files.each do |f|
        # Check for match if sublet was reordered
        Dir[@path_sublets + "/*"].each do |file|
          a = File.basename(f)
          b = File.basename(file)

          if a == b or File.fnmatch("[0-9_]*#{a}", b)
            puts ">>>>>> Uninstalling file `#{b}'"
            FileUtils.remove_file(File.join(@path_sublets, b), true)
          end
        end
      end

      # Uninstall icons
      spec.icons.each do |f|
        puts ">>>>>> Uninstalling icon `#{f}'"
        FileUtils.remove_file(
          File.join(@path_icons, File.basename(f)), true
        )
      end

      # Uninstall specification
      puts ">>>>>> Uninstalling specification `#{spec.to_s}.spec'"
      FileUtils.remove_file(
        File.join(@path_specs, spec.to_s + ".spec"),
        true
      )

      puts ">>> Uninstalled sublet #{spec.to_s}"
    else
      puts ">>> WARNING: Cannot find sublet `#{name}' in local "                   "repository"
    end
  end

  build_local(true)

  reload_sublets if reload
end
unpack (names, version = nil, use_tags = false)
Sur::Client::unpack {{{

Unpack sublet to current path

@param [Array] names Names of Sublets @param [String] version Version of the Sublet @param [Bool] use_tags Use tags

@raise [String] Unpack error @since 0.0

@example

Sur::Client.new.unpack("sublet")
=> nil
[show source]
# File data/sur/client.rb, line 629
def unpack(names, version = nil, use_tags = false)
  build_remote

  # Install all sublets
  names.each do |name|
    # Check if sublet is installed
    if (specs = search(name, @cache_remote, version, use_tags)) and
        !specs.empty?
      spec = specs.first

      # Download and unpack sublet
      unless (temp = download(spec)).nil?
        base  = File.join(Dir.pwd, spec.to_str)
        icons = File.join(base, "icons")

        FileUtils.mkdir_p([ icons ])

        install_sublet(temp.path, base, icons, base)
      end
    end
  end

  build_local(true)
end
update (repo)
Sur::Client::update {{{

Update a repository

@param [String] repo Repo name

@since 0.0

@example

Sur::Client.new.update("remote")
=> nil
[show source]
# File data/sur/client.rb, line 665
def update(repo)
  case repo
    when "local"
      build_local(true)
    when "remote"
      build_remote(true)
  end
end
upgrade (use_color = true, reload = false, assume = false)
Sur::Client::upgrade {{{

Upgrade all Sublets

@param [Bool] use_color Use colors @param [Bool] reload Reload sublets after uninstalling @param [Bool] assume Whether to assume yes

@raise Upgrade error @since 0.2

@example

Sur::Client.new.upgrade
=> nil
[show source]
# File data/sur/client.rb, line 688
def upgrade(use_color = true, reload = false, assume = false)
  build_local
  build_remote

  list = []

  # Iterate over server-side sorted list
  @cache_local.each do |spec_a|
    @cache_remote.each do |spec_b|
      if spec_a.name == spec_b.name and
          spec_a.version.to_f < spec_b.version.to_f
        list << spec_b.name

        if use_color
          puts ">>> %s: %s -> %s" % [
            spec_a.name,
            colorize(5, spec_a.version),
            colorize(2, spec_b.version)
          ]
        else
           puts ">>> %s: %s -> %s" % [
            spec_a.name, spec_a.version, spec_b.version
          ]
        end

        break
      end
    end
  end

  return if list.empty?

  # Really?
  unless assume
    print ">>> Upgrade sublets (y/n)? "

    return unless "y" == STDIN.readline.strip.downcase
  end

  # Finally upgrade
  uninstall(list)
  install(list)

  reload_sublets if reload
end
yank (use_color = true, reload = false, assume = false)
Sur::Client::yank {{{

Delete a sublet from remote server

@param [String] name Name of the Sublet @param [String] version Version of the Sublet

@raise Upgrade error @since 0.2

@example

Sur::Client.new.yank("subtle", "0.0")
=> nil
[show source]
# File data/sur/client.rb, line 747
def yank(use_color = true, reload = false, assume = false)
  raise NotImplementedError
end