Class: Ronin::Repository

Inherits:
Object
  • Object
show all
Includes:
DataPaths, Model, Model::HasAuthors, Model::HasLicense
Defined in:
lib/ronin/repository.rb

Overview

Represents a container for user scripts and miscallaneous code, that can be distributed over common SCMs (Git, Mercurial (Hg), SubVersion (SVN), Rsync).

Constant Summary collapse

LOCAL_DOMAIN =

The default domain that repositories are added from

'localhost'
METADATA_FILE =

Repository metadata file name

'ronin.yml'
BIN_DIR =

Repository bin/ directory

'bin'
LIB_DIR =

Repository lib/ directory

'lib'
INIT_FILE =

The init.rb file to load from the LIB_DIR

'init.rb'
DATA_DIR =

Repository data/ directory

'data'
SCRIPT_DIRS =

Directories containing Scripts

%w[scripts cache]

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Model::HasLicense

included

Methods included from Model::HasAuthors

included

Methods included from Model

included

Constructor Details

#initialize(attributes = {}) {|repo| ... } ⇒ Repository

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Creates a new Ronin::Repository object.

Parameters:

  • attributes (Hash) (defaults to: {})

    The attributes of the repository.

  • path (String)

    The path to the repository.

  • scm (Symbol)

    The SCM used by the repository. Can be either:

    • :git
    • :mercurial / :hg
    • :sub_version / :svn
    • :rsync
  • uri (String, URI::HTTP, URI::HTTPS)

    The URI the repository resides at.

Yields:

  • (repo)

    If a block is given, the repository will be passed to it.

Yield Parameters:

  • repo (Repository)

    The newly created repository.


146
147
148
149
150
151
152
153
154
155
156
157
158
159
# File 'lib/ronin/repository.rb', line 146

def initialize(attributes={})
  super(attributes)

  @bin_dir = self.path.join(BIN_DIR)
  @lib_dir = self.path.join(LIB_DIR)
  @data_dir = self.path.join(DATA_DIR)
  @script_dirs = SCRIPT_DIRS.map { |dir| self.path.join(dir) }

  @activated = false

  

  yield self if block_given?
end

Instance Attribute Details

#bin_dirObject (readonly)

The bin/ directory


107
108
109
# File 'lib/ronin/repository.rb', line 107

def bin_dir
  @bin_dir
end

#data_dirObject (readonly)

The data/ directory


113
114
115
# File 'lib/ronin/repository.rb', line 113

def data_dir
  @data_dir
end

#lib_dirObject (readonly)

The lib/ directory


110
111
112
# File 'lib/ronin/repository.rb', line 110

def lib_dir
  @lib_dir
end

#script_dirsObject (readonly)

Directories containing Scripts.


116
117
118
# File 'lib/ronin/repository.rb', line 116

def script_dirs
  @script_dirs
end

Class Method Details

.activate!Array<Repository>

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Activates all installed or added repositories.

Returns:

  • (Array<Repository>)

    The activated repository.

See Also:

Since:

  • 1.0.0


385
386
387
# File 'lib/ronin/repository.rb', line 385

def Repository.activate!
  Repository.each { |repo| repo.activate! }
end

.add!(options = {}) ⇒ Repository

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Adds an Repository with the given options.

Returns:

Raises:

  • (ArgumentError)

    The :path option was not specified.

  • (RepositoryNotFound)

    The path of the repository did not exist or was not a directory.

  • (DuplicateRepository)

    The repository was already added or installed.

Since:

  • 1.0.0


220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
# File 'lib/ronin/repository.rb', line 220

def Repository.add!(options={})
  unless options.has_key?(:path)
    raise(ArgumentError,"the :path option was not given")
  end

  path = Pathname.new(options[:path]).expand_path

  unless path.directory?
    raise(RepositoryNotFound,"Repository #{path} cannot be found")
  end

  if Repository.count(:path => path) > 0
    raise(DuplicateRepository,"a Repository at the path #{path} was already added")
  end

  # create the repository
  repo = Repository.new(options.merge(
    :path => path,
    :installed => false,
    :domain => LOCAL_DOMAIN
  ))

  if Repository.count(:name => repo.name, :domain => repo.domain) > 0
    raise(DuplicateRepository,"the Repository #{repo} already exists in the database")
  end

  # save the repository
  if repo.save
    # cache any files from within the `cache/` directory of the
    # repository
    repo.cache_scripts!
  end

  return repo
end

.deactivate!Array<Repository>

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

De-activates all installed or added repositories.

Returns:

  • (Array<Repository>)

    The de-activated repositories.

See Also:

Since:

  • 1.0.0


401
402
403
# File 'lib/ronin/repository.rb', line 401

def Repository.deactivate!
  Repository.reverse_each { |repo| repo.deactivate! }
end

.find(name) ⇒ Repository

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Searches for the Repository with a given name, and potentially installed from the given domain.

Examples:

Load the repository with the given name

Repository.find('postmodern-repo')

Load the repository with the given name and domain.

Repository.find('postmodern-repo/github.com')

Parameters:

  • name (String)

    The name of the repository.

Returns:

Raises:

Since:

  • 1.0.0


184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
# File 'lib/ronin/repository.rb', line 184

def Repository.find(name)
  name, domain = name.to_s.split('/',2)

  query = {:name => name}
  query[:domain] = domain if domain

  unless (repo = Repository.first(query))
    if domain
      raise(RepositoryNotFound,"Repository #{name.dump} from domain #{domain.dump} cannot be found")
    else
      raise(RepositoryNotFound,"Repository #{name.dump} cannot be found")
    end
  end

  return repo
end

.install!(options = {}) ⇒ Repository

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Installs an repository.

Parameters:

  • options (Hash) (defaults to: {})

    Additional options.

Options Hash (options):

  • :uri (Addressable::URI, String)

    The URI to the repository.

  • :scm (Symbol)

    The SCM used by the repository. May be either:

    • :git
    • :mercurial / :hg
    • :sub_version / :svn
    • :rsync

Returns:

  • (Repository)

    The newly installed repository.

Raises:

  • (ArgumentError)

    The :uri option must be specified.

  • (DuplicateRepository)

    An repository already exists with the same name and host properties.

Since:

  • 1.0.0


287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
# File 'lib/ronin/repository.rb', line 287

def Repository.install!(options={})
  unless options[:uri]
    raise(ArgumentError,":uri must be passed to Repository.install")
  end

  remote_repo = Pullr::RemoteRepository.new(options)
  name = remote_repo.name
  domain = if remote_repo.uri.scheme
             remote_repo.uri.host
           else
             # Use a regexp to pull out the host-name, if the URI
             # lacks a scheme.
             remote_repo.uri.to_s.match(/\@([^@:\/]+)/)[1]
           end

  if Repository.count(:name => name, :domain => domain) > 0
    raise(DuplicateRepository,"a Repository already exists with the name #{name.dump} from domain #{domain.dump}")
  end

  path = File.join(Config::REPOS_DIR,name,domain)

  # pull down the remote repository
  local_repo = remote_repo.pull(path)

  # add the new remote repository
  repo = Repository.new(
    :path => path,
    :scm => local_repo.scm,
    :uri => remote_repo.uri,
    :installed => true,
    :name => name,
    :domain => domain
  )

  # save the repository 
  if repo.save
    # cache any files from within the `cache/` directory of the
    # repository
    repo.cache_scripts!
  end

  return repo
end

.uninstall!(name) ⇒ nil

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Uninstalls the repository with the given name or domain.

Examples:

Uninstall the repository with the given name

Repository.uninstall!('postmodern-repo')

Uninstall the repository with the given name and domain.

Repository.uninstall!('postmodern-repo/github.com')

Parameters:

  • name (String)

    The name of the repository to uninstall.

Returns:

  • (nil)

369
370
371
# File 'lib/ronin/repository.rb', line 369

def Repository.uninstall!(name)
  Repository.find(name).uninstall!
end

.update! {|repo| ... } ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Updates all repositories.

Yields:

  • (repo)

    If a block is given, it will be passed each updated repository.

Yield Parameters:

Since:

  • 1.0.0


344
345
346
347
348
349
350
351
# File 'lib/ronin/repository.rb', line 344

def Repository.update!
  Repository.each do |repo|
    # update the repositories contents
    repo.update!

    yield repo if block_given?
  end
end

Instance Method Details

#activate!Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Activates the repository by adding the #lib_dir to the $LOAD_PATH global variable.


497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
# File 'lib/ronin/repository.rb', line 497

def activate!
  # add the data/ directory
  register_data_path(@data_dir) if @data_dir.directory?

  if @lib_dir.directory?
    # ensure all paths added to $LOAD_PATH are Strings
    path = @lib_dir.to_s

    $LOAD_PATH << path unless $LOAD_PATH.include?(path)
  end

  # load the lib/init.rb file
  init_path = self.path.join(LIB_DIR,INIT_FILE)
  require init_path if init_path.file?

  @activated = true
  return true
end

#activated?Boolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Determines if the repository has been activated.

Returns:

  • (Boolean)

    Specifies whether the repository has been activated.


487
488
489
# File 'lib/ronin/repository.rb', line 487

def activated?
  @activated == true
end

#cache_scripts!Repository

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Clears the #script_paths and re-saves the cached files within the cache/ directory.

Returns:

Since:

  • 1.0.0


561
562
563
564
565
566
567
568
569
# File 'lib/ronin/repository.rb', line 561

def cache_scripts!
  clean_scripts!

  each_script do |path|
    self.script_paths.new(:path => path).cache
  end

  return self
end

#clean_scripts!Repository

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Deletes any #script_paths associated with the repository.

Returns:

Since:

  • 1.0.0


617
618
619
620
# File 'lib/ronin/repository.rb', line 617

def clean_scripts!
  self.script_paths.clear
  return self
end

#deactivate!Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

De-activates the repository by removing the #lib_dir from the $LOAD_PATH global variable.


522
523
524
525
526
527
528
529
# File 'lib/ronin/repository.rb', line 522

def deactivate!
  unregister_data_paths

  $LOAD_PATH.delete(@lib_dir.to_s)

  @activated = false
  return true
end

#each_script {|path| ... } ⇒ Enumerator

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

All paths within the cache/ directory of the repository.

Yields:

  • (path)

    If a block is given, it will be passed each matching path.

Yield Parameters:

  • path (Pathname)

    A matching path.

Returns:

  • (Enumerator)

    If no block is given, an Enumerator object will be returned.

Since:

  • 1.0.0


471
472
473
474
475
476
477
# File 'lib/ronin/repository.rb', line 471

def each_script(&block)
  return enum_for(:each_script) unless block

  @script_dirs.each do |dir|
    Pathname.glob(dir.join('**','*.rb'),&block)
  end
end

#executablesArray<String>

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

The executable scripts in the bin/ directory.

Returns:

  • (Array<String>)

    The executable script names.

Since:

  • 1.0.0


443
444
445
446
447
448
449
450
451
452
453
# File 'lib/ronin/repository.rb', line 443

def executables
  scripts = []

  if @bin_dir.directory?
    @bin_dir.entries.each do |path|
      scripts << path.basename.to_s if path.file?
    end
  end

  return scripts
end

#find_script(sub_path) ⇒ Script::Path?

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Finds a cached script.

Parameters:

  • sub_path (String)

    The sub-path within the repository to search for.

Returns:

Since:

  • 1.1.0


544
545
546
547
548
# File 'lib/ronin/repository.rb', line 544

def find_script(sub_path)
  paths = @script_dirs.map { |dir| File.join(dir,sub_path) }

  return script_paths.first(:path => paths)
end

#initialize_metadataObject (protected)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Loads the metadata from METADATA_FILE within the repository.


711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
# File 'lib/ronin/repository.rb', line 711

def 
   = self.path.join(METADATA_FILE)

  self.title = self.name
  self.description = nil
  self.license = nil

  self.source = self.uri
  self.website = self.source
  self.authors.clear

  if File.file?()
     = YAML.load_file()

    if (title = ['title'])
      self.title = title
    end

    if (description = ['description'])
      self.description = description
    end

    if (license = ['license'])
      self.license = License.first_or_predefined(:name => license)
    end

    if (uri = ['uri'])
      self.uri ||= uri
    end

    if (source = ['source'])
      self.source = source
    end

    if (website = ['website'])
      self.website = website
    end

    case ['authors']
    when Hash
      ['authors'].each do |name,email|
        self.authors << Author.first_or_new(:name => name, :email => email)
      end
    when Array
      ['authors'].each do |name|
        self.authors << Author.first_or_new(:name => name)
      end
    end
  end

  return self
end

#local?Boolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Determines if the repository was added locally.

Returns:

  • (Boolean)

    Specifies whether the repository was added locally.

Since:

  • 1.0.0


415
416
417
# File 'lib/ronin/repository.rb', line 415

def local?
  self.domain == LOCAL_DOMAIN
end

#remote?Boolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Determines if the repository was installed remotely.

Returns:

  • (Boolean)

    Specifies whether the repository was installed from a remote URI.

Since:

  • 1.0.0


429
430
431
# File 'lib/ronin/repository.rb', line 429

def remote?
  self.domain != LOCAL_DOMAIN
end

#sync_scripts!Repository

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Syncs the #script_paths of the repository, and adds any new cached files.

Returns:

Since:

  • 1.0.0


582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
# File 'lib/ronin/repository.rb', line 582

def sync_scripts!
  # activates the repository before caching it's objects
  activate!

  new_paths = each_script.to_a

  self.script_paths.each do |script_path|
    # filter out pre-existing paths within the `cached/` directory
    new_paths.delete(script_path.path)

    # sync the cached file and catch any exceptions
    script_path.sync
  end

  # cache the new paths within the `cache/` directory
  new_paths.each do |path|
    self.script_paths.new(:path => path).cache
  end

  # deactivates the repository
  deactivate!

  return self
end

#to_sString

Converts the repository to a String.

Returns:

  • (String)

    The name and domain of the repository.


700
701
702
# File 'lib/ronin/repository.rb', line 700

def to_s
  "#{self.name}/#{self.domain}"
end

#uninstall! {|repo| ... } ⇒ Repository

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Deletes the contents of the repository.

Yields:

  • (repo)

    If a block is given, it will be passed the repository after it's contents have been deleted.

Yield Parameters:

Returns:

Since:

  • 1.0.0


679
680
681
682
683
684
685
686
687
688
689
690
691
692
# File 'lib/ronin/repository.rb', line 679

def uninstall!
  deactivate!

  FileUtils.rm_rf(self.path) if self.installed?

  # destroy any cached files first
  clean_scripts!

  # remove the repository from the database
  destroy if saved?

  yield self if block_given?
  return self
end

#update! {|repo| ... } ⇒ Repository

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Updates the repository, reloads it's metadata and syncs the cached files of the repository.

Yields:

  • (repo)

    If a block is given, it will be passed after the repository has been updated.

Yield Parameters:

Returns:

Since:

  • 1.0.0


640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
# File 'lib/ronin/repository.rb', line 640

def update!
  local_repo = Pullr::LocalRepository.new(
    :path => self.path,
    :scm => self.scm
  )

  # only update if we have a repository
  local_repo.update(self.uri)

  # re-initialize the metadata
  

  # save the repository
  if save
    # syncs the cached files of the repository
    sync_scripts!
  end

  yield self if block_given?
  return self
end