Class: Lazylead::Task::Svn::Touch

Inherits:
Object
  • Object
show all
Defined in:
lib/lazylead/task/svn/touch.rb

Overview

Send notification about modification of critical files in svn repo.

Instance Method Summary collapse

Constructor Details

#initialize(log = Log.new) ⇒ Touch

Returns a new instance of Touch.



39
40
41
# File 'lib/lazylead/task/svn/touch.rb', line 39

def initialize(log = Log.new)
  @log = log
end

Instance Method Details

#locations(opts) ⇒ Object

TODO:

#567/DEV Performance: improve the glob pattern to support multiple files. Right now in order to find all branches for a particular file we are using glob pattern

Right now for each file we initiate a separate search request, thus we need to think how to avoid this and send only one search request

Return for each file all his locations considering branches

> locations('readme.md')
branches/0.13.x/readme.md
trunk/readme.md


111
112
113
114
115
116
117
118
119
120
121
# File 'lib/lazylead/task/svn/touch.rb', line 111

def locations(opts)
  opts.slice("files", ",").flat_map do |file|
    raw = OS.new.run "svn ls --no-auth-cache ",
                     "--username #{opts.decrypt('svn_user', 'svn_salt')}",
                     "--password #{opts.decrypt('svn_password', 'svn_salt')}",
                     "--xml -R --search \"#{file}\" #{opts['svn_url']}"
    Nokogiri.XML(raw, nil, "UTF-8")
            .xpath("/lists/list/entry/name/text()")
            .map { |f| f.to_s.strip }
  end
end

#run(_, postman, opts) ⇒ Object



43
44
45
46
# File 'lib/lazylead/task/svn/touch.rb', line 43

def run(_, postman, opts)
  commits = touch(opts)
  postman.send(opts.merge(entries: commits)) unless commits.empty?
end

#svn_log(opts) ⇒ Object

Return svn commits history for file(s) within particular date range in repo



61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/lazylead/task/svn/touch.rb', line 61

def svn_log(opts)
  now = if opts.key? "now"
          DateTime.parse(opts["now"])
        else
          DateTime.now
        end
  start = (now.to_time - opts["period"].to_i).to_datetime
  locations(opts).flat_map do |file|
    raw = OS.new.run "svn log --no-auth-cache",
                     "--username #{opts.decrypt('svn_user', 'svn_salt')}",
                     "--password #{opts.decrypt('svn_password', 'svn_salt')}",
                     "--xml -v -r {#{start}}:{#{now}} #{opts['svn_url']}/#{file}"
    Nokogiri.XML(raw, nil, "UTF-8")
            .xpath("//logentry[paths/path]")
            .map { |xml| to_entry(xml) }
  end
end

#to_entry(xml) ⇒ Object

Convert single revision(XML text) to entry object. Entry object is a simple ruby struct object.



81
82
83
84
85
86
87
88
89
# File 'lib/lazylead/task/svn/touch.rb', line 81

def to_entry(xml)
  e = to_struct(Hash.from_xml(xml.to_s.strip)).logentry
  if e.paths.path.respond_to? :each
    e.paths.path.each(&:strip!)
  else
    e.paths.path.strip!
  end
  e
end

#to_struct(hsh) ⇒ Object

Make a simple ruby struct object from hash hierarchically,

considering nested hash(es) (if applicable)


93
94
95
96
97
# File 'lib/lazylead/task/svn/touch.rb', line 93

def to_struct(hsh)
  OpenStruct.new(
    hsh.transform_values { |v| v.is_a?(Hash) ? to_struct(v) : v }
  )
end

#touch(opts) ⇒ Object

Return all svn commits for a particular date range, which are touching

somehow the critical files within the svn repo.


50
51
52
53
54
55
56
57
58
# File 'lib/lazylead/task/svn/touch.rb', line 50

def touch(opts)
  files = opts.slice("files", ",")
  branches = opts.slice("branches", ",")
  svn_log(opts)
    .select { |e| branches.empty? || branches.any? { |b| e.paths.path.start_with? b } }
    .each do |e|
    e.paths.path.delete_if { |p| files.none? { |f| p.include? f } } if e.paths.path.respond_to? :delete_if
  end
end