Class: EnhanceRepo::RpmMd::UpdateInfo

Inherits:
Data
  • Object
show all
Defined in:
lib/enhance_repo/rpm_md/update_info.rb

Instance Method Summary collapse

Methods inherited from Data

#metadata_filename, #name, #should_compress?

Methods included from Logger

#log

Constructor Details

#initialize(config) ⇒ UpdateInfo

Returns a new instance of UpdateInfo.



43
44
45
46
47
48
49
# File 'lib/enhance_repo/rpm_md/update_info.rb', line 43

def initialize(config)
  @dir = config.dir
  @basedir = config.updatesbasedir

  # update files
  @updates = Set.new
end

Instance Method Details

#empty?Boolean

Returns:

  • (Boolean)


51
52
53
# File 'lib/enhance_repo/rpm_md/update_info.rb', line 51

def empty?
  @updates.empty?
end

#generate_update(packages, outputdir) ⇒ Object

generates a patch from a list of package names it compares the last version of those package names with their previous ones

outputdir is the directory where to save the patch to.



77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
# File 'lib/enhance_repo/rpm_md/update_info.rb', line 77

def generate_update(packages, outputdir)
  
  # make a hash name -> array of packages
  log.info "Generating update part to #{outputdir} for packages #{packages.join(", ")}"
  package_index = {}

  # look all rpms in the old packages base directory plus
  # the ones in the current one
  rpmfiles = [ Dir["#{@dir}/**/*.rpm"], @basedir.nil? ? [] : Dir["#{@basedir}/**/*.rpm"]].flatten
  log.info "`-> #{rpmfiles.size} rpm packages"
  # reject unwanted files
  rpmfiles.reject! do |rpmfile|
    reject = false
    # reject all delta and src rpms
    reject = true if rpmfile =~ /\.delta\.rpm$|\.src\.rpm$/
    # now reject all the packages for which the rpm file name
    # does not match the name of the requested packages
    # so if packages is A, B and we have C-1.0.rpm it does not
    # match either /A/ nor /B/ so we reject it.
    reject = true if packages.select { |pkg| rpmfile =~ /#{pkg.gsub(/\+/, "\\\\+")}/ }.empty?
    reject
  end

  log.info "`-> #{rpmfiles.size} rpm packages were not discarded"
  log.debug "    #{rpmfiles.map { |x| File.basename(x) }.join(', ')}"
  
  # now index all rpms per package name in a hash table
  # which goes from name => list of versions
  rpmfiles.each do |rpmfile|
    rpm = PackageId.new(rpmfile)
    # now that we have the real name, reject if it is not part
    # of the requested packages to generate updates for
    next if not packages.include?(rpm.name)
    
    package_index[rpm.name] = Array.new if not package_index.has_key?(rpm.name)
    # add the rpm if there is no other rpm with the same version
    package_index[rpm.name] << rpm if not package_index[rpm.name].select { |x| x.version == rpm.version && x.name == rpm.name }.first
  end

  log.info "`-> indexed #{package_index.size} unique packages from #{rpmfiles.size} rpms"
  log.debug "    #{package_index.keys.join(', ')}"
  # do our package hash include every package?
  packages.reject! do |pkg|
    reject = false
    if not package_index.has_key?(pkg)
      log.warn "`-> the package '#{pkg}' is not available in the repository."
      reject = true
    end
    reject
  end

  update = Update.new
  
  packages.each do |pkgname|
    pkglist = package_index[pkgname]
    log.info "`-> #{pkglist.size} versions for '#{pkgname}'"
    log.debug "    #{package_index[pkgname].map {|x| x.version}.join(", ")}"
    # sort them by version
    pkglist.sort! { |a,b| a.version <=> b.version }
    pkglist.reverse!
    # now that the list is sorted, the new rpm is the first

    # if there is only one package then we don't need changelog
    if pkglist.size > 1
      # we know that there are no duplicate versions so we can
      # take the first and the second            
      first = pkglist.shift
      second = pkglist.shift
      diff = first.changelog - second.changelog || []
      #diff = first.changelog[0, first.changelog.size - second.changelog.size] || []                        
      log.info "`-> found change #{first.ident} and #{second.ident}."
      
      log.info "`-> '#{pkgname}' has #{diff.size} change entries (#{first.changelog.size}/#{second.changelog.size})"
      update.packages << first
      diff.each do |entry|
        update.description << entry.text << "\n"          
      end
    else
      # jump to next pkgname
      next
    end
    
  end

  # do not save it if there are no packages
  if update.empty?

  end
  
  # before writing the update, figure out more
  # information
  update.smart_fill_blank_fields

  log.info "`-> update has #{update.references.size} references"
  log.debug "    #{update.references.join(',')} "
  
  filename = ""

  FileUtils.mkdir_p outputdir
  # increase version until version is available
  while ( File.exists?(filename = File.join(outputdir, update.suggested_filename + ".xml") ))
    update.version += 1
  end
  log.info "Saving update part to '#{filename}'."
  
  File.open(filename, 'w') do |f|
    update.write(f)
  end
end

#read_repoparts(opts = {}) ⇒ Object

add all updates in a repoparts directory by default look in repoparts/ otherwise pass the :repoparts_path option



62
63
64
65
66
67
68
69
70
# File 'lib/enhance_repo/rpm_md/update_info.rb', line 62

def read_repoparts(opts={})
  repoparts_path = opts[:repoparts_path] || File.join(@dir, 'repoparts')
  log.info "Reading update parts from #{repoparts_path}"
  Dir[File.join(repoparts_path, 'update-*.xml')].each do |updatefile|
    log.info("`-> adding update #{updatefile}")
    @updates << updatefile
  end
  # end of directory iteration
end

#sizeObject



55
56
57
# File 'lib/enhance_repo/rpm_md/update_info.rb', line 55

def size
  @updates.size
end

#split_updates(outputdir) ⇒ Object

splits the updateinfo file into serveral update files it writes those files into outputdir output filenames will be id+_splited_version.xml where id is the update id version is incremented when there is others update files with the same id

outputdir is the directory where to save the patch to.



195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
# File 'lib/enhance_repo/rpm_md/update_info.rb', line 195

def split_updates(outputdir)
  FileUtils.mkdir_p outputdir        
  updateinfofile = File.join(@dir, )

  # we can't split without an updateinfo file
  raise "#{updateinfofile} does not exist" if not File.exist?(updateinfofile)
  Zlib::GzipReader.open(updateinfofile) do |gz|        
    document = REXML::Document.new(gz)
    root = document.root
    root.each_element("update") do |updateElement|
      id = nil
      updateElement.each_element("id") do |elementId|
        id = elementId.text
      end
      if id == nil
        log.warning 'No id found. Setting id to NON_ID_FOUND'
        id = 'NON_ID_FOUND'
      end
      version = 0
      updatefilename = ""
      while ( File.exists?(updatefilename = File.join(outputdir, "update-#{id}_splited_#{version.to_s}.xml") ) )
        version += 1
      end
      log.info "Saving update part to '#{updatefilename}'."
      File.open(updatefilename, 'w') do |updatefile|
        updatefile << updateElement
      end
    end
  end
end

#write(file) ⇒ Object

write a update out



227
228
229
230
231
232
233
234
235
236
237
238
# File 'lib/enhance_repo/rpm_md/update_info.rb', line 227

def write(file)
  builder = Builder::XmlMarkup.new(:target=>file, :indent=>2)
  builder.instruct!
  xml = builder.updates do |b|
    @updates.each do |update|
      File.open(update) do |f|
        file << f.read
      end
      #update.append_to_builder(b)
    end
  end #done builder
end