class DFiles

DFiles is used to manage the updating of the files-repository on the Profeda-installations.

Attributes

dir_base[RW]
dir_descs[RW]
dir_files[RW]
url_html[RW]

Public Class Methods

hash(name) click to toggle source

Returns a hash of the file-content

# File Entities/DFiles.rb, line 272
def self.hash(name)
  if File.exists?(name)
    return IO.read(name).bytes.inject { |a, b| a + a * b } % (2**64-1)
  end
  return 0
end

Public Instance Methods

get_limited_files(files, size_limit) click to toggle source

Returns the first files so that the total is not above the size_limit

# File Entities/DFiles.rb, line 183
def get_limited_files(files, size_limit)
  ret = files.dup
  if size_limit > 0
    # Prioritize the files
    while ret.inject(0) { |tot, f| tot + f.file_size } > size_limit
      # We have too many files and need to prune some entries
      ret.delete(ret.last)
    end
  end
  ret
end
get_size(dir, files) click to toggle source
# File Entities/DFiles.rb, line 195
def get_size(dir, files)
  files.inject(0) { |tot, file|
    tot += File.size(dir + "/#{file}")
  }
end
get_tags(tag) click to toggle source

get_tags returns all tags with the most common tags at the beginning

# File Entities/DFiles.rb, line 202
def get_tags(tag)
  # Get a list of all tags wihtout the priority
  tags = search_by_tags(tag).collect { |df| df.tags.collect { |_, t| t } }.flatten.sort
  # Count how many times each tag appears and sort inversely
  tags_count = tags.uniq.collect { |t| [tags.count(t), t] }.sort { |a, b| b[0] <=> a[0] }
  # Remove the counter
  tags_count.collect { |_, t| t }
end
html_tag_files(tags) click to toggle source
# File Entities/DFiles.rb, line 260
def html_tag_files(tags)
  "<div class='files'><ul>\n" +
      DFiles.search_by_all(:tags, tags.to_a).collect { |df|
        "<li><a href='../files/#{df.save_file}'>" +
            "#{df.name}</a> - #{df.desc} - " +
            "<a href='#{df.url_page}'>#{df.url_page}</a>" +
            "</li>"
      }.join("\n") +
      "</ul></div>"
end
load(has_static = true) click to toggle source

searches for all descriptions in @dir_descs

# File Entities/DFiles.rb, line 44
def load(has_static = true)
  #dputs_func
  delete_all(true)
  dputs(2) { "Loading descs from #{@dir_descs}" }
  if Dir.exists?(@dir_descs)
    dputs(4) { 'Directory exists' }
    file_id = 1
    Dir.glob("#{@dir_descs}/*.desc").each { |f|
      dputs(4) { "Working on file #{f}" }
      name = File.basename(f)
      lines = IO.readlines(f).collect { |l| l.chomp }
      if lines.size >= 7
        file = {
            dfile_id: file_id,
            desc_file: name,
            name: name.sub(/.desc$/, ''),
            url_file: lines[0],
            url_page: lines[1],
            desc: lines[3],
            os: lines[5],
            category: lines[6],
            tags: lines[5..-1].collect { |t|
              t.split(' ')
            }
        }
        if file[:url_file][0] == ':'
          su = file[:url_file].match(/^:([^:]*):(.*)$/)
          file[:save_file] = su[1]
          file[:url_file] = su[2]
        else
          file[:save_file] = File.basename(file[:url_file])
        end
        dputs(3) { "Saving description #{file}" }
        file_path = File.join(@dir_files, file[:save_file])
        file[:file_size] = File.exists?(file_path) ? File.size(file_path) : 0
        @data[file_id] = file
        file_id += 1
      else
        dputs(2) { "Description #{f} has not enough lines, skipping" }
      end
    }
  else
    dputs(2) { "Didn't find directory #{@dir_descs}" }
  end
  dputs(3) { @data.inspect }
end
save() click to toggle source

saves back the descriptions to @dir_descs

# File Entities/DFiles.rb, line 92
def save()
  return unless @changed
  if Dir.exists?(@dir_descs)
    FileUtils.rm(Dir.glob("#{@dir_descs}/*.desc"))
  else
    FileUtils.mkpath(@dir_descs)
  end
  @data.each { |k, v|
    File.open("#{@dir_descs}/#{v[:desc_file]}", 'w') { |f|
      if (file = v[:save_file]) != File.basename(v[:url_file])
        v[:url_file] = ":#{file}:#{v[:url_file]}"
      end

      f.puts(v[:url_file], v[:url_page], '',
             v[:desc], '',
             v[:os], v[:category])
      v[:tags].each { |t| f.puts(t.join(' ')) }
    }
  }
end
save_html(file, text) click to toggle source
# File Entities/DFiles.rb, line 247
def save_html(file, text)
  html = IO.read(File.join(@dir_base, 'index_pre.html')) +
      text +
      IO.read(File.join(@dir_base, 'index_post.html'))
  IO.write(File.join(@dir_base, file), html)
end
set_dir_base(dir) click to toggle source
# File Entities/DFiles.rb, line 35
def set_dir_base(dir)
  @dir_base = dir
  @dir_files = File.join(@dir_base, 'files')
  @dir_descs = File.join(@dir_base, 'descs')
  @dir_html = File.join(@dir_base, 'html')
  @url_html = 'http://files.ndjair.net/'
end
setup_data() click to toggle source
# File Entities/DFiles.rb, line 9
def setup_data
  value_int :dfile_id
  value_str :name
  value_str :desc_file
  # url_file holds the url to the file. It can be preceded
  # by a name held between two ":", which will be the
  # save_file-name. Else the save_file-name is the 'basename' of the
  # url_file
  value_str :url_file
  value_str :save_file
  value_str :url_page
  value_str :desc
  # os and category are used to build the dokuwiki-pages
  value_str :os
  value_str :category
  # tags are additional fields
  value_str :tags
  value_int :file_size

  # Only used once a DFile is found - will not be stored, but represents
  # the priority that will be used for pruning.
  value_int :priority

  set_dir_base('/opt/Files')
end
update_desc_from_dir(update_dir) click to toggle source

updates the descriptions from a directory (probably a mount-point, has to be mounted before)

# File Entities/DFiles.rb, line 115
def update_desc_from_dir(update_dir)
  return unless Dir.exists?(update_dir)
  Dir.glob(File.join(update_dir, '*.desc')).each { |f|
    name = File.basename(f)
    local_name = File.join(@dir_descs, name)
    if File.size(f) == 0
      # This is a file that has to be removed
      File.rm(local_name)
    else
      dputs(3) { "Copying #{f} to #{local_name}" }
      FileUtils.cp(f, local_name)
    end
  }
  load
end
update_files_from_dir(update_dir) click to toggle source

copies the files from a directory to @dir_files

# File Entities/DFiles.rb, line 132
def update_files_from_dir(update_dir)
  #dputs_func
  load
  unless Dir.exists? @dir_files
    FileUtils.mkpath @dir_files
  end
  # Update all sizes, delete if file is missing
  search_all_.each { |df|
    df.file_size = 0
    [@dir_files, update_dir].each { |d|
      file = File.join(d, df.save_file)
      if File.exists?(file)
        df.file_size = File.size(file)
        dputs(3) { "Found file #{file} with size #{df.file_size}" }
      else
        df.file_size = 0
      end
    }
    if df.file_size == 0
      df.delete
    end
  }

  files_wanted = get_limited_files(DFilePriorities.get_most_wanted,
                                   DFileConfig.limit_size * 2**30).
      collect { |f| f.save_file }
  files_here = Dir.glob(File.join(@dir_files, '/*')).
      collect { |f| File.basename(f) }
  files_delete = files_here - files_wanted
  files_copy = files_wanted - files_here
  dputs(3) { "Files to delete are: #{files_delete}" }
  dputs(3) { "Files to copy are: #{files_delete}" }

  # Delete not used files
  files_delete.each { |f|
    file = File.join(@dir_files, f)
    dputs(3) { "Deleting file #{file}" }
    FileUtils.rm(file)
  }

  # Copy new files
  files_copy.each { |f|
    file = File.join(update_dir, f)
    dputs(3) { "Copying file #{file}" }
    FileUtils.cp(file, @dir_files)
  }
  save
end
update_html() click to toggle source

creates html-files for downloading the files

# File Entities/DFiles.rb, line 212
def update_html
  used_tags = %w(windows mac linux android media).select { |tag|
    get_tags(tag).size > 0 }

  # First create index.html
  save_html('index.html',
            "<ul>\n" +
                used_tags.collect { |tag|
                  "<li><a href='#{@url_html}/html/#{tag}_all.html'>#{tag.capitalize}</a>"
                }.join("\n") +
                "</ul>\n")

  unless File.exists?(@dir_html)
    FileUtils.mkdir(@dir_html)
  end
  # Add each main tag that exists
  used_tags.each { |tag|
    save_html(File.join('html', "#{tag}_all.html"),
              "<h1>#{tag.capitalize}</h1>\n" +
                  html_tag_links(tag) +
                  "<h3><a href='../index.html'>Home</a></h3>" +
                  html_tag_files(tag)
    )
    # Add tag-files
    (get_tags(tag) - [tag]).each { |t|
      save_html(File.join('html', "#{tag}_#{t}.html"),
                "<h1><a href='#{tag}_all.html'>#{tag.capitalize}</a></h1>\n" +
                "<h2 class='subtitle'>#{t.capitalize}</h2>" +
                    html_tag_links(tag) +
                    "<h4 class='back'><a href='../index.html'>Home</a></h4>" +
                    html_tag_files([tag, t]))
    }
  }
end