get rid of old SVN structure

This commit is contained in:
Ward Wouts 2020-03-11 07:23:11 +01:00
parent 64eaf7c89f
commit 08e83501be
324 changed files with 0 additions and 70245 deletions

1087
news/article.rb Normal file

File diff suppressed because it is too large Load diff

529
news/newsrc.rb Normal file
View file

@ -0,0 +1,529 @@
# $Dwarf: newsrc.rb,v 1.13 2004/06/16 08:16:58 ward Exp $
# $Source$
#
# Copyright (c) 2002, 2003 Ward Wouts <ward@wouts.nl>
#
# Permission to use, copy, modify, and distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#
require Pathname.new(__FILE__).dirname + "../set/intspan"
#require "thread"
module News
class Newsrc
#@@save_lock = Mutex.new
def initialize(file=nil)
@newsrc = { "group" => Hash.new, "list" => Array.new }
if file
unless load(file)
puts "Can't load #{file}"
exit
end
end
end
def load(file=nil)
file = "#{ENV['HOME']}/.newsrc" unless file
@newsrc["file"] = file
@newsrc["group"] = {}
@newsrc["list"] = []
if FileTest.file?( "#{file}" ) and FileTest.readable?( "#{file}" )
lines = IO.readlines("#{file}")
import_rc(lines)
end
return true
end
def import_rc(lines)
@newsrc["group"] = {}
@newsrc["list"] = []
linenumber = 1
lines.each{|line|
parse(line)
}
end
def parse(line)
unless line =~ /^([^!:]+)([!:])\s(.*)$/x
puts "Newsrc.parse: Bad newsrc line: #{line}"
exit
end
name = $1
mark = $2
articles = $3
unless Set::IntSpan.valid(articles)
puts "Newsrc.parse: Bad article list: #{line}"
end
group = { "name" => name, "subscribed" => (mark == ":"),
"articles" => Set::IntSpan.new(articles)}
@newsrc["group"][name] = group
@newsrc["list"].push(group)
end
def save
unless @newsrc.has_key?("file")
@newsrc["file"] = "#{$ENV['HOME']}/.newsrc"
end
save_as(@newsrc["file"])
end
# this is not thread safe! (well, it should be now)
def save_as(file)
# @@save_lock.synchronize{
if FileTest.exists?("#{file}")
begin
FileUtils.mv(file, "#{file}.bak")
rescue
puts "Can't rename #{file}, #{file}.bak: #{$!}"
exit
end
end
begin
newsrc = File.new(file, "w")
newsrc.flock(File::LOCK_EX)
rescue
puts "Can't open #{file}: #{$!}"
exit
end
@newsrc["file"] = file
@newsrc["list"].each{|group|
newsrc.print format(group)
}
newsrc.sync
newsrc.flock(File::LOCK_UN) # what's the right order here?
newsrc.close
# }
end
# Here 'group' is a group structure. It'd probably be much more useful if
# it could just be a group_name_; which it can now.
def save_group(group)
unless @newsrc.has_key?("file")
@newsrc["file"] = "#{$ENV['HOME']}/.newsrc"
end
if group.class.to_s == "String"
groupname = group.dup
@newsrc["list"].each{|g|
if g["name"] == groupname
group = g.dup
break
end
}
end
save_group_as(@newsrc["file"], group)
end
# This should be thread safe, but may not be. It needs testing!
# If not, mutexes are needed.
def save_group_as(file, group)
# @@save_lock.synchronize{
#p Time.now
#p "copy file"
if FileTest.exists?("#{file}")
begin
FileUtils.copy(file, "#{file}.bak")
rescue
puts "Can't copy #{file} to #{file}.bak: #{$!}"
end
end
#p Time.now
#p "open & lock file"
begin
if FileTest.exists?("#{file}")
newsrc = File.new(file, "r+")
else
newsrc = File.new(file, "w")
end
newsrc.flock(File::LOCK_EX)
rescue
puts "Can't open #{file}: #{$!}"
exit
end
#p Time.now
#p "opened & locked"
# read file
lines = newsrc.readlines
# pointer -> 0
newsrc.rewind
group_saved = false
# write read stuff & replace group
lines.each{|line|
# same parsing as the parse method uses
unless line =~ /^([^!:]+)([!:])\s(.*)$/x
puts "Newsrc.parse: Bad newsrc line: #{line}"
# restore backup on failure, it'll contain the flaw too, but it'll
# be complete
begin
FileUtils.copy("#{file}.bak", file)
rescue
puts "Can't copy #{file}.bak to #{file}: #{$!}"
end
exit
end
linegroup = $1
if linegroup == group["name"]
newsrc.print format(group)
group_saved = true
else
newsrc.print line
end
}
if ! group_saved
newsrc.print format(group)
end
#p Time.now
#p "truncate, sync, unlock & close file"
# sometimes the file grows and then shrinks
# this is because a 'read' line van become shorter when more
# articles have been read (1,3,5 vs 1-5)
# when this happens the file needs to be truncated
pos = newsrc.pos
newsrc.truncate(pos)
newsrc.sync
newsrc.flock(File::LOCK_UN) # what's the right order here?
newsrc.close
#p Time.now
#p "garbage collect"
#p Time.now
GC.start
# }
end
def format(group)
name = group["name"]
sub = group["subscribed"] ? ':' : '!'
articles = group["articles"].run_list
return "#{name}#{sub} #{articles}\n"
end
def export_rc
lines = @newsrc["list"].collect{ |group|
name = group["name"]
sub = group["subscribed"] ? ':' : '!'
articles = group["articles"].run_list
space = articles ? ' ' : ''
"#{name}#{sub}#{space}#{articles}\n" }
return lines
end
def add_group(name, options)
if @newsrc["group"].has_key?(name)
options.has_key?("replace") or return false
del_group(name)
end
group = {"name" => name,
"subscribed" => true,
"articles" => Set::IntSpan.new }
@newsrc["group"][name] = group
_insert(group, options)
return true
end
def move_group(name, options)
if @newsrc["group"].has_key?(name)
group = @newsrc["group"][name]
else
return false
end
@newsrc["list"] = @newsrc["list"].delete_if{|x| x["name"] == name}
_insert(group, options)
return true
end
def _insert(group, options)
list = @newsrc["list"]
where = ""
arg = ""
if options.has_key?("where")
where = options["where"]
end
arg = where.slice!(1) if where.class.to_s == "Array"
case where.to_s
when "first"
@newsrc["list"].unshift(group)
when "last"
@newsrc["list"].push(group)
when ""
@newsrc["list"].push(group) # default
when "alpha"
alpha(group)
when "before"
before(group, arg)
when "after"
after(group, arg)
when "number"
number(group, arg)
end
end
def alpha (group)
name = group["name"]
(0...@newsrc["list"].length).each{|i|
if ((name <=> @newsrc["list"][i]["name"]) == -1)
upper = @newsrc["list"].slice!(i..@newsrc["list"].length)
@newsrc["list"].push(group)
@newsrc["list"].push(upper)
return;
end
}
@newsrc["list"].push(group)
end
def before(group, before)
name = group["name"]
(0...@newsrc["list"].length).each{|i|
if (@newsrc["list"][i]["name"] == before.to_s)
upper = @newsrc["list"].slice!(i..@newsrc["list"].length)
@newsrc["list"].push(group)
@newsrc["list"].push(upper)
return;
end
}
@newsrc["list"].push(group)
end
def after(group, after)
name = group["name"]
(0...@newsrc["list"].length).each{|i|
if (@newsrc["list"][i]["name"] == after.to_s)
upper = @newsrc["list"].slice!((i+1)..@newsrc["list"].length)
@newsrc["list"].push(group)
@newsrc["list"].push(upper)
return;
end
}
@newsrc["list"].push(group)
end
def number(group, offset)
offset = @newsrc["list"].length if offset[0] > @newsrc["list"].length
upper = @newsrc["list"].slice!(offset..@newsrc["list"].length)
@newsrc["list"].push(group)
@newsrc["list"].push(upper)
end
def del_group(name)
if @newsrc["group"].has_key?(name)
group = @newsrc["group"][name]
else
return false
end
@newsrc["group"].delete(name)
@newsrc["list"] = @newsrc["list"].delete_if{|x| x["name"] == name}
return true
end
def subscribe(name, options = {"where" => ""})
unless @newsrc["group"].has_key?(name)
add_group(name, options)
end
@newsrc["group"][name]["subscribed"] = true
end
def unsubscribe(name, options = {"where" => ""})
unless @newsrc["group"].has_key?(name)
add_group(name, options)
end
@newsrc["group"][name]["subscribed"] = false
end
def mark(name, article, options = {"where" => ""})
unless @newsrc["group"].has_key?(name)
add_group(name, options)
end
@newsrc["group"][name]["articles"].insert!(article)
end
def mark_list(name, list, options = {"where" => ""})
unless @newsrc["group"].has_key?(name)
add_group(name, options)
end
articles = @newsrc["group"][name]["articles"].union(list)
@newsrc["group"][name]["articles"] = articles
end
def mark_range(name, from, to, options = {"where" => ""})
unless @newsrc["group"].has_key?(name)
add_group(name, options)
end
range = Set::IntSpan.new("#{from}-#{to}")
articles = @newsrc["group"][name]["articles"].union(range)
@newsrc["group"][name]["articles"] = articles
end
def unmark(name, article, options = {"where" => ""})
unless @newsrc["group"].has_key?(name)
add_group(name, options)
end
@newsrc["group"][name]["articles"].remove(article)
end
def unmark_list(name, list, options = {"where" => ""})
unless @newsrc["group"].has_key?(name)
add_group(name, options)
end
articles = @newsrc["group"][name]["articles"].diff(list)
@newsrc["group"][name]["articles"] = articles
end
def unmark_range(name, from, to, options = {"where" => ""})
unless @newsrc["group"].has_key?(name)
add_group(name, options)
end
range = Set::IntSpan.new("#{from}-#{to}")
articles = @newsrc["group"][name]["articles"].diff(range)
@newsrc["group"][name]["articles"] = articles
end
def exists(name)
return @newsrc["group"].has_key?(name) ? true : false
end
def subscribed(name)
exists(name) and @newsrc["group"][name]["subscribed"]
end
def marked(name, article)
exists(name) and @newsrc["group"][name]["articles"].member?(article)
end
def num_groups
return @newsrc["list"].length
end
def groups
list = @newsrc["list"].dup
list.collect!{|x| x["name"]}
end
def sub_groups
list = @newsrc["list"].dup
list.collect!{|x| x["subscribed"] ? x["name"] : nil}.compact!
end
def unsub_groups
list = @newsrc["list"].dup
list.collect!{|x| x["subscribed"] ? nil : x["name"]}.compact!
end
def marked_articles(name, options = {"where" => ""})
unless @newsrc["group"].has_key?(name)
add_group(name, options)
end
return @newsrc["group"][name]["articles"].elements
end
def unmarked_articles(name, from, to, options = {"where" => ""})
unless @newsrc["group"].has_key?(name)
add_group(name, options)
end
range = Set::IntSpan.new("#{from}-#{to}")
return range.diff(@newsrc["group"][name]["articles"]).elements
end
def get_articles(name, options = {"where" => ""})
unless @newsrc["group"].has_key?(name)
add_group(name, options)
end
@newsrc["group"][name]["articles"].run_list
end
def set_articles(name, articles, options = {"where" => ""})
Set::IntSpan.valid(articles) or return false
set = Set::IntSpan.new(articles)
set.finite or return false
min = set.min
min != nil and min < 0 and return false
unless @newsrc["group"].has_key?(name)
add_group(name, options)
end
@newsrc["group"][name]["articles"] = set
return true
end
end # class
end # module
# TODO
# Do not kill an item until it's tested!
# [x] new
# [x] load
# [ ] _scan # Initializes a Newsrc object from a string. Used for testing.
# [x] import_rc
# [x] parse # parses a single line from a newsrc file
# [x] save
# [x] save_as
# [ ] save_group
# [ ] save_group_as
# [x] format
# [x] export_rc
# [ ] _dump # Formats a Newsrc object to a string. Used for testing
# [x] add_group
# [x] move_group
# [x] Splice(\@$$@) # heet nu number en is simpeler
# [x] _insert
# [x] Alpha
# [x] Before
# [x] After
# [x] del_group
# [x] subscribe
# [x] unsubscribe
# [x] mark
# [x] mark_list
# [x] mark_range
# [x] unmark
# [x] unmark_list
# [x] unmark_range
# [x] exists
# [x] subscribed
# [x] marked
# [x] num_groups
# [x] groups
# [x] sub_groups
# [x] unsub_groups
# [x] marked_articles
# [x] unmarked_articles
# [x] get_articles
# [x] set_articles

File diff suppressed because one or more lines are too long

16
news/tests/newsrc_test.rb Executable file
View file

@ -0,0 +1,16 @@
#!/usr/local/bin/ruby
require '../newsrc.rb'
def test1
print "Test 1\n"
@newsrc = News::Newsrc.new("newsrc.news.wizeazz.nl")
print @newsrc.get_articles("alt.binaries.sounds.mp3.gothic-industrial")
print "\n"
@newsrc.unmark_range("alt.binaries.sounds.mp3.gothic-industrial", 0, 2394540)
print @newsrc.get_articles("alt.binaries.sounds.mp3.gothic-industrial")
print "\n"
end
test1