Class: Debci::Repository

Inherits:
Object
  • Object
show all
Defined in:
lib/debci/repository.rb

Overview

This class implements the backend access to the debci data files. Normally you should access the data through objects of the Debci::Package class, which you can obtain by calling this class' find_package method.

>> repository = Debci::Repository.new
>> package = repository.find_package('mypackage')

Defined Under Namespace

Classes: PackageNotFound

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(path = nil) ⇒ Repository

:nodoc:



19
20
21
22
23
# File 'lib/debci/repository.rb', line 19

def initialize(path=nil) # :nodoc:
  path ||= Debci.config.data_basedir
  @path = path
  @data_dirs = Dir.glob(File.join(path, 'packages', '*', '*')).reject { |d| d =~ /\.old$/ }
end

Instance Attribute Details

#pathObject (readonly)

Returns the value of attribute path



17
18
19
# File 'lib/debci/repository.rb', line 17

def path
  @path
end

Instance Method Details

#architecturesObject

Returns an Array of architectures known to this debci instance



31
32
33
# File 'lib/debci/repository.rb', line 31

def architectures
  @architectures ||= @data_dirs.map { |d| File.basename(d) }.uniq.sort
end

#architectures_for(package) ⇒ Object

Returns an Array of architectures for which there is data for package.



73
74
75
76
# File 'lib/debci/repository.rb', line 73

def architectures_for(package)
  package = String(package)
  data_dirs_for(package).map { |d| File.basename(d) }.uniq
end

#each_packageObject

Iterates over all packages

For each package in the repostory, a Debci::Package object will be passed in to the block passed.

Example:

repository.each_package do |pkg| puts pkg end



104
105
106
107
108
109
# File 'lib/debci/repository.rb', line 104

def each_package
  packages.sort.each do |pkgname|
    pkg = Debci::Package.new(pkgname, self)
    yield pkg
  end
end

#find_package(name) ⇒ Object

Returns a single package by its names.

Raises a Debci::PackageNotFound is there is no package with that name.



85
86
87
88
89
90
91
# File 'lib/debci/repository.rb', line 85

def find_package(name)
  if !packages.include?(name)
    raise PackageNotFound.new(name)
  end

  Debci::Package.new(name, self)
end

#history_for(package, suite, architecture) ⇒ Object

Backend implementation for Debci::Package#history



152
153
154
155
156
157
158
159
160
161
162
163
164
165
# File 'lib/debci/repository.rb', line 152

def history_for(package, suite, architecture)
  return unless File.exists?(file = File.join(data_dir(suite, architecture, package), 'history.json'))

  entries = nil

  File.open(file) do |f|
    entries = JSON.load(f)
  end

  entries
    .map { |test| Debci::Status.from_data(test, suite, architecture) }
    .sort_by(&:date)
    .reverse
end

#news_for(package, n = 10) ⇒ Object

Backend implementation for Debci::Package#news



168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
# File 'lib/debci/repository.rb', line 168

def news_for(package, n=10)
  suites = '{' + self.suites.join(',') + '}'
  architectures = '{' + self.architectures.join(',') + '}'
  history = Dir.glob(File.join(data_dir(suites, architectures, package), '[0-9]*.json')).sort_by { |f| File.basename(f) }

  news = []

  while !history.empty?
    file = history.pop
    dir = File.expand_path(File.dirname(file) + '/../..')
    suite = File.basename(File.dirname(dir))
    architecture = File.basename(dir)
    status = load_status(file, suite, architecture)
    if status.newsworthy?
      news << status
    end
    if news.size >= n
      break
    end
  end

  news
end

#packagesObject

Returns a Set of packages known to this debci instance



36
37
38
# File 'lib/debci/repository.rb', line 36

def packages
  @packages ||= (@data_dirs.map { |d| Dir.glob(File.join(d, '*/*')) }.flatten.map { |d| File.basename(d) } + Debci.blacklist.packages.keys).to_set
end

#platform_specific_issuesObject



140
141
142
143
144
145
146
147
148
149
# File 'lib/debci/repository.rb', line 140

def platform_specific_issues
  result = {}
  packages.each do |package|
    statuses = status_for(package).flatten
    if statuses.map(&:status).reject { |s| [:no_test_data, :tmpfail].include?(s) }.uniq.size > 1
      result[package] = statuses
    end
  end
  result
end

#prefixesObject

Returns an Array of package prefixes known to this debci instance



41
42
43
# File 'lib/debci/repository.rb', line 41

def prefixes
  @prefixes ||= @data_dirs.map { |d| Dir.glob(File.join(d, '*/')) }.flatten.map { |d| File.basename(d) }.uniq.sort
end

#search(query) ⇒ Object

Searches packages by name.

Returns a sorted Array of Debci::Package objects. On an exact match, it will return an Array with a single element. Otherwise all packages that match the query (which is converted into a regular expression) are returned.



117
118
119
120
121
122
123
124
125
126
127
128
# File 'lib/debci/repository.rb', line 117

def search(query)
  # first try exact match
  match = packages.select { |p| p == query }

  # then try regexp match
  if match.empty?
    re = Regexp.new(query)
    match = packages.select { |p| p =~ re }
  end

  match.sort.map { |p| Debci::Package.new(p, self) }
end

#slow_packagesObject



60
61
62
63
64
# File 'lib/debci/repository.rb', line 60

def slow_packages
  all_statuses.select do |status|
    status.duration_seconds && status.duration_seconds > 60 * 60 # 1h
  end
end

#status_for(package) ⇒ Object

Backend implementation for Debci::Package#status



131
132
133
134
135
136
137
138
# File 'lib/debci/repository.rb', line 131

def status_for(package)
  architectures.map do |arch|
    suites.map do |suite|
      status_file = File.join(data_dir(suite, arch, package), 'latest.json')
      load_status(status_file, suite, arch)
    end
  end
end

#status_history(suite, architecture) ⇒ Object

Returns the status history for this debci instance



193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
# File 'lib/debci/repository.rb', line 193

def status_history(suite, architecture)
  return unless File.exists?(file = File.join(status_dir(suite, architecture), 'history.json'))

  data = nil

  begin
    File.open(file, 'r') do |f|
      data = JSON.load(f)
    end
  rescue JSON::ParserError
    true
  end

  data
end

#suitesObject

Returns an Array of suites known to this debci instance



26
27
28
# File 'lib/debci/repository.rb', line 26

def suites
  @suites ||= Dir.glob(File.join(@path, 'packages', '*')).reject { |d| d =~ /\.old$/ }.map { |d| File.basename(d) }.sort
end

#suites_for(package) ⇒ Object

Returns an Array of suites for which there is data for package.



67
68
69
70
# File 'lib/debci/repository.rb', line 67

def suites_for(package)
  package = String(package)
  data_dirs_for(package).map { |d| File.basename(File.dirname(d)) }.uniq
end

#tmpfail_packagesObject

Returns a Set of packages known to this debci instance that are temporarily failing. If no packages are temporarily failing, nothing is returned.



48
49
50
51
52
53
54
55
56
57
58
# File 'lib/debci/repository.rb', line 48

def tmpfail_packages
  tmpfail_packages = Set.new

  all_statuses.each do |status|
    if status.status == :tmpfail
      tmpfail_packages << status.package
    end
  end

  tmpfail_packages.sort.map { |p| Debci::Package.new(p, self) }
end