Skip to content

Instantly share code, notes, and snippets.

@zerebubuth
Created February 13, 2012 14:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zerebubuth/1817152 to your computer and use it in GitHub Desktop.
Save zerebubuth/1817152 to your computer and use it in GitHub Desktop.
Pseudo-ruby for ODbL change "bot"
class Cleaner
def is_clean?(obj)
# objects tagged odbl=clean are defined as clean by the user, so
# we take this version as definitively clean, regardless of any
# prior history.
if obj.has_tag? "odbl" => "clean"
return true
else
# otherwise, this version is clean if and only if the previous
# version is clean (or this is the first version) *AND* the
# user (or adoptive user) who edited this object has agreed.
if obj.is_first_version? or is_clean?(obj.previous_version)
cs = obj.changeset
return cs.user.accepted_cts? or cs.adopted_user.accepted_cts?
else
# last chance for an object to be clean is if retains no
# information since the last dirty version.
dirty_version = obj
dirty_version = dirty_version.previuos_version while is_clean?(dirty_version)
return is_harmless?(dirty_version)
end
end
end
def is_harmless?(obj, dirty_obj)
# if the dirty version is a node move less than 1m and the previous
# version is clean, then this is a harmless edit.
if is_clean?(dirty_obj.previous_version)
if obj.is_node? and distance(dirty_obj, dirty_obj.previous_version) < 1m
return true
end
end
# if the tags on the current object include some of the keys
# used in the dirty version, then the object cannot be clean
if obj.tags.keys.any? {|k| dirty_obj.tags.has_key? k}
return false
end
case obj.type
when :node
# if the current object is a node and has been moved since the
# last dirty version then it's clean
if distance(obj, dirty_obj) > 0
return true
end
when :way
# if the current object contains none of the nds used in
# the dirty object then it's clean.
if not obj.nds.any? {|n| dirty_obj.nds.include? n}
return true
end
when :relation
# ???
end
return false
end
def action_to_clean(type, id, objects_to_delete)
obj_versions = @db.get_all_versions(type, id)
current_version = obj_versions.last
dirty_versions = obj_versions.select {|o| not is_clean?(o)}
if not is_clean?(current_version)
clean_versions = obj_versions.select {|o| is_clean?(o)}
if clean_versions.empty?
# no clean versions - we must delete this object
# and redact all versions of it. it might not be
# possible to delete the object right now, as it
# may be used in other objects - if so, then defer
# that action for later.
if is_used?(type, id)
@objects_to_delete << [type, id]
else
delete(type, id)
obj_versions.each {|o| redact(o)}
end
else
# some clean versions, so revert to the latest
# of these and redact all others.
revert(type, id, clean_versions.last)
dirty_versions.each {|o| redact(o)}
end
else
# current version is clean, so just need to redact
# any dirty previous versions.
dirty_versions.each {|o| redact(o)}
end
end
def clean
@objects_to_delete = []
# clean all the objects we can at this point
@db.all_objects do |type, id|
action_to_clean(type, id)
end
# now just left with things to delete - which may
# require that we modify some other objects.
objs_to_modify = {}
@objects_to_delete.each do |type, id|
dependents(type, id).each do |d_type, d_id|
objs_to_modify[d_type, d_id] << [type, id]
end
end
objs_to_modify.each do |d_type, d_id|
# remove references to values in key
end
@objects_to_delete.each do |type, id|
obj_versions = @db.get_all_versions(type, id)
delete(type, id)
obj_versions.each {|o| redact(o)}
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment