/usr/share/pepper/activity.lua is in pepper 0.3.2-3.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 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 186 | --[[
pepper - SCM statistics report generator
Copyright (C) 2010-2012 Jonas Gehring
Released under the GNU General Public License, version 3.
Please see the COPYING file in the source distribution for license
terms and conditions, or see http://www.gnu.org/licenses/.
file: activity.lua
Visualizes several repository activity metrics using a smoothed curve.
This is a port of http://labs.freehackers.org/wiki/hgactivity
--]]
require "pepper.datetime"
require "pepper.plotutils"
-- Describes the report
function describe(self)
local r = {}
r.name = "Activity"
r.description = "General repository activity"
r.options = {
{"-bARG, --branch=ARG", "Select branch"},
{"--tags[=ARG]", "Add tag markers to the graph, optionally filtered with a regular expression"},
{"-c, --changes, -l", "Count line changes instead of commit counts"},
{"--split=ARG", "Split the graph by 'authors', 'files', 'directories', or 'none' (the default)"},
{"-nARG", "Maximum number of series when using --split"}
}
pepper.datetime.add_daterange_options(r)
pepper.plotutils.add_plot_options(r)
return r
end
-- Revision callback function
function count(r)
local date = r:date()
if date == 0 then return end
local n = 1
if count_changes ~= nil then
n = r:diffstat():lines_added() + r:diffstat():lines_removed()
end
if split == "none" then
if activity[date] == nil then activity[date] = n
else activity[date] = activity[date] + n end
elseif split == "authors" then
if activity[r:author()] == nil then activity[r:author()] = {} end
if activity[r:author()][date] == nil then activity[r:author()][date] = n
else activity[r:author()][date] = activity[r:author()][date] + n end
elseif split == "directories" or split == "files" then
local s = r:diffstat()
local dir = (split == "directories")
for i,v in ipairs(s:files()) do
if count_changes ~= nil then
n = s:lines_added(v) + s:lines_removed(v)
end
if dir then v = pepper.utils.dirname("/" .. v) end
if activity[v] == nil then activity[v] = {} end
if activity[v][date] == nil then
activity[v][date] = n
else
activity[v][date] = activity[v][date] + n
end
end
end
-- Track date range
if date < firstdate then firstdate = date end
if date > lastdate then lastdate = date end
end
-- This is mostly from hg's activity extension
function convolution(datemin, datemax, data)
local date = datemin
local wmin = 1
local wmax = 1
local number = 1000 -- number of points we want to compute
local period = (datemax-datemin)/number -- period at which we compute a value
local wperiod = period * 25 -- length of the convolution window
local dates = {}
local values = {}
local mydates = {}
for k,v in pairs(data) do
table.insert(mydates, k)
end
table.sort(mydates)
local length = #mydates
for x = 0, number do
date = date + period
while wmin <= length and mydates[wmin] < date - wperiod do
wmin = wmin + 1
end
while wmax <= length and mydates[wmax] < date + wperiod do
wmax = wmax + 1
end
value = 0
for a = wmin, wmax-1 do
local delta = mydates[a] - date
value = value + data[mydates[a]] * (1 - delta/wperiod)
end
table.insert(values, value)
table.insert(dates, date)
end
return dates, values
end
-- Returns the size of a table
function tablesize(t)
local n = 0
for k,v in pairs(t) do
n = n + 1
end
return n
end
-- Main report function
function run(self)
activity = {}
firstdate = os.time()
lastdate = 0
count_changes = self:getopt("c,changes,l")
split = self:getopt("split", "none")
if split == "n" then split="none"
elseif split == "a" then split="authors"
elseif split == "f" then split="files"
elseif split == "d" then split="directories" end
if ({none=1, authors=1, files=1, branches=1, directories=1})[split] == nil then
error("Unknown split option '" .. split .. "'")
end
-- Gather data
local repo = self:repository()
local branch = self:getopt("b,branch", repo:default_branch())
local datemin, datemax = pepper.datetime.date_range(self)
repo:iterator(branch, {start=datemin, stop=datemax}):map(count)
if last == 0 then
error("No data on this branch")
end
local p = pepper.gnuplot:new()
pepper.plotutils.setup_output(p)
if split == "none" then
pepper.plotutils.setup_std_time(p)
p:set_title("Activity (on " .. branch .. ")")
else
pepper.plotutils.setup_std_time(p, {key = "below"})
p:set_title("Activity by " .. string.upper(split:sub(1, 1)) .. split:sub(2) .. " (on " .. branch .. ")")
end
p:cmd("set noytics")
if self:getopt("tags") ~= nil then
pepper.plotutils.add_tagmarks(p, repo, self:getopt("tags", "*"))
end
-- Generate graphs
p:set_xrange_time(firstdate, lastdate)
if split == "none" then
local dates, values = convolution(firstdate, lastdate, activity)
p:plot_series(dates, values, {}, "lines smooth bezier linewidth 1.5")
else
-- Determine contributions (i.e. frequent entries)
local freqs = {}
for k,v in pairs(activity) do
table.insert(freqs, {k, tablesize(v)})
end
table.sort(freqs, function (a,b) return (a[2] > b[2]) end)
local n = 1 + tonumber(self:getopt("n", 6))
local i = 1
local vdates = {}
local values = {}
local keys = {}
while i <= #freqs and i < n do
vdates[i], values[i] = convolution(firstdate, lastdate, activity[freqs[i][1]])
keys[i] = freqs[i][1]
i = i + 1
end
p:plot_multi_series(vdates, values, keys, "lines smooth bezier linewidth 1.5")
end
end
|