keithsalisbury-subtrac 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (139) hide show
  1. data/LICENSE +20 -0
  2. data/README.rdoc +7 -0
  3. data/Rakefile +56 -0
  4. data/VERSION.yml +4 -0
  5. data/bin/subtrac +40 -0
  6. data/lib/subtrac.rb +245 -0
  7. data/lib/subtrac/common/clients/index.wsgi +89 -0
  8. data/lib/subtrac/common/favicon.ico +0 -0
  9. data/lib/subtrac/common/images/trac/banner_bg.jpg +0 -0
  10. data/lib/subtrac/common/images/trac/bar_bg.gif +0 -0
  11. data/lib/subtrac/common/images/trac/footer_back.png +0 -0
  12. data/lib/subtrac/common/images/trac/main_bg.gif +0 -0
  13. data/lib/subtrac/common/images/trac/saint_logo_small.png +0 -0
  14. data/lib/subtrac/common/static/404.html +14 -0
  15. data/lib/subtrac/common/styles/trac.css +222 -0
  16. data/lib/subtrac/common/trac.ini +178 -0
  17. data/lib/subtrac/config/config.yml +54 -0
  18. data/lib/subtrac/passwords +1 -0
  19. data/lib/subtrac/shared/trac.ini +178 -0
  20. data/lib/subtrac/templates/location.erb +16 -0
  21. data/lib/subtrac/templates/projects/blank/svn/branches/README +0 -0
  22. data/lib/subtrac/templates/projects/blank/svn/tags/README +0 -0
  23. data/lib/subtrac/templates/projects/blank/svn/trunk/README +0 -0
  24. data/lib/subtrac/templates/projects/blank/trac/wiki/WikiStart +57 -0
  25. data/lib/subtrac/templates/projects/new/svn/trunk/trac/wiki/WikiStart +46 -0
  26. data/lib/subtrac/templates/projects/new/trac/wiki/WikiStart +23 -0
  27. data/lib/subtrac/templates/projects/trac_theme/svn/trunk/index/index.html +22 -0
  28. data/lib/subtrac/templates/projects/trac_theme/svn/trunk/templates/layout.html +56 -0
  29. data/lib/subtrac/templates/projects/trac_theme/svn/trunk/templates/site.html +27 -0
  30. data/lib/subtrac/templates/projects/trac_theme/svn/trunk/templates/theme.html +86 -0
  31. data/lib/subtrac/templates/projects/trac_theme/trac/wiki/WikiStart +4 -0
  32. data/lib/subtrac/templates/trac.erb +25 -0
  33. data/lib/subtrac/templates/vhost.erb +35 -0
  34. data/lib/subtrac/trac-plugins/advancedticketworkflowplugin/advancedworkflow/__init__.py +0 -0
  35. data/lib/subtrac/trac-plugins/advancedticketworkflowplugin/advancedworkflow/controller.py +419 -0
  36. data/lib/subtrac/trac-plugins/advancedticketworkflowplugin/setup.cfg +3 -0
  37. data/lib/subtrac/trac-plugins/advancedticketworkflowplugin/setup.py +20 -0
  38. data/lib/subtrac/trac-plugins/clientsplugin/clients/__init__.py +0 -0
  39. data/lib/subtrac/trac-plugins/clientsplugin/clients/action.py +28 -0
  40. data/lib/subtrac/trac-plugins/clientsplugin/clients/action_email.py +168 -0
  41. data/lib/subtrac/trac-plugins/clientsplugin/clients/action_zendesk_forum.py +137 -0
  42. data/lib/subtrac/trac-plugins/clientsplugin/clients/admin.py +91 -0
  43. data/lib/subtrac/trac-plugins/clientsplugin/clients/api.py +199 -0
  44. data/lib/subtrac/trac-plugins/clientsplugin/clients/client.py +105 -0
  45. data/lib/subtrac/trac-plugins/clientsplugin/clients/events.py +287 -0
  46. data/lib/subtrac/trac-plugins/clientsplugin/clients/eventsadmin.py +71 -0
  47. data/lib/subtrac/trac-plugins/clientsplugin/clients/htdocs/clients.css +4 -0
  48. data/lib/subtrac/trac-plugins/clientsplugin/clients/model.py +135 -0
  49. data/lib/subtrac/trac-plugins/clientsplugin/clients/processor.py +70 -0
  50. data/lib/subtrac/trac-plugins/clientsplugin/clients/reportmanager.py +142 -0
  51. data/lib/subtrac/trac-plugins/clientsplugin/clients/reports.py +231 -0
  52. data/lib/subtrac/trac-plugins/clientsplugin/clients/summary.py +27 -0
  53. data/lib/subtrac/trac-plugins/clientsplugin/clients/summary_milestone.py +152 -0
  54. data/lib/subtrac/trac-plugins/clientsplugin/clients/summary_ticketchanges.py +160 -0
  55. data/lib/subtrac/trac-plugins/clientsplugin/clients/templates/admin_client_events.html +124 -0
  56. data/lib/subtrac/trac-plugins/clientsplugin/clients/templates/admin_clients.html +134 -0
  57. data/lib/subtrac/trac-plugins/clientsplugin/cron/changes.xslt +132 -0
  58. data/lib/subtrac/trac-plugins/clientsplugin/cron/run-client-event +97 -0
  59. data/lib/subtrac/trac-plugins/clientsplugin/cron/summary.xslt +161 -0
  60. data/lib/subtrac/trac-plugins/clientsplugin/setup.py +43 -0
  61. data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/__init__.py +4 -0
  62. data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/burndownchart.py +273 -0
  63. data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/hoursinplaceeditor.py +44 -0
  64. data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/hoursremaining.py +36 -0
  65. data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/htdocs/jquery-1.2.3.min.js +32 -0
  66. data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/htdocs/jquery.jeditable.js +409 -0
  67. data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/htdocs/jquery.jeditable.mini.js +30 -0
  68. data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/templates/edithours.html +53 -0
  69. data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/tests/burndownchart.py +181 -0
  70. data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/tests/hoursremaining.py +66 -0
  71. data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/tests/workloadchart.py +47 -0
  72. data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/utils.py +93 -0
  73. data/lib/subtrac/trac-plugins/estimationtoolsplugin/estimationtools/workloadchart.py +86 -0
  74. data/lib/subtrac/trac-plugins/estimationtoolsplugin/setup.py +20 -0
  75. data/lib/subtrac/trac-plugins/timingandestimationplugin/scripts/SumRollups.js +23 -0
  76. data/lib/subtrac/trac-plugins/timingandestimationplugin/scripts/adw_tracdb.py +128 -0
  77. data/lib/subtrac/trac-plugins/timingandestimationplugin/scripts/git-post-receive +40 -0
  78. data/lib/subtrac/trac-plugins/timingandestimationplugin/scripts/trac-post-commit.py +285 -0
  79. data/lib/subtrac/trac-plugins/timingandestimationplugin/scripts/trac_billing.py +173 -0
  80. data/lib/subtrac/trac-plugins/timingandestimationplugin/scripts/utils/__init__.py +0 -0
  81. data/lib/subtrac/trac-plugins/timingandestimationplugin/scripts/utils/mail.py +164 -0
  82. data/lib/subtrac/trac-plugins/timingandestimationplugin/setup.py +69 -0
  83. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/__init__.py +1 -0
  84. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/api.py +292 -0
  85. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/blackmagic.py +172 -0
  86. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/dbhelper.py +178 -0
  87. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/htdocs/billingplugin.css +25 -0
  88. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/htdocs/field_disabler.js +6 -0
  89. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/htdocs/formatDate.js +356 -0
  90. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/htdocs/js/tip_centerwindow.js +100 -0
  91. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/htdocs/js/tip_followscroll.js +84 -0
  92. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/htdocs/js/wz_tooltip.js +1149 -0
  93. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/htdocs/linkifyer.js +119 -0
  94. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/htdocs/query.js +73 -0
  95. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/htdocs/ticket.js +165 -0
  96. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/query_webui.py +28 -0
  97. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/reportmanager.py +221 -0
  98. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/reports.py +675 -0
  99. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/reports_filter.py +150 -0
  100. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/statuses.py +25 -0
  101. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/tande_filters.py +131 -0
  102. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/templates/billing.cs +84 -0
  103. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/templates/billing.html +104 -0
  104. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/ticket_daemon.py +194 -0
  105. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/ticket_policy.py +62 -0
  106. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/ticket_webui.py +28 -0
  107. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/usermanual.py +127 -0
  108. data/lib/subtrac/trac-plugins/timingandestimationplugin/timingandestimationplugin/webui.py +129 -0
  109. data/lib/subtrac/trac-plugins/worklogplugin/setup.py +29 -0
  110. data/lib/subtrac/trac-plugins/worklogplugin/worklog/__init__.py +1 -0
  111. data/lib/subtrac/trac-plugins/worklogplugin/worklog/api.py +187 -0
  112. data/lib/subtrac/trac-plugins/worklogplugin/worklog/htdocs/jqModal.css +40 -0
  113. data/lib/subtrac/trac-plugins/worklogplugin/worklog/htdocs/jqModal.js +67 -0
  114. data/lib/subtrac/trac-plugins/worklogplugin/worklog/htdocs/jquery.mousewheel.pack.js +12 -0
  115. data/lib/subtrac/trac-plugins/worklogplugin/worklog/htdocs/jquery.timeentry.pack.js +7 -0
  116. data/lib/subtrac/trac-plugins/worklogplugin/worklog/htdocs/tracWorklog.js +40 -0
  117. data/lib/subtrac/trac-plugins/worklogplugin/worklog/htdocs/ui.datepicker.css +208 -0
  118. data/lib/subtrac/trac-plugins/worklogplugin/worklog/htdocs/ui.datepicker.js +1439 -0
  119. data/lib/subtrac/trac-plugins/worklogplugin/worklog/htdocs/work.png +0 -0
  120. data/lib/subtrac/trac-plugins/worklogplugin/worklog/htdocs/work.xcf +0 -0
  121. data/lib/subtrac/trac-plugins/worklogplugin/worklog/htdocs/worklogplugin.css +80 -0
  122. data/lib/subtrac/trac-plugins/worklogplugin/worklog/htdocs/workstart.png +0 -0
  123. data/lib/subtrac/trac-plugins/worklogplugin/worklog/htdocs/workstop.png +0 -0
  124. data/lib/subtrac/trac-plugins/worklogplugin/worklog/manager.py +336 -0
  125. data/lib/subtrac/trac-plugins/worklogplugin/worklog/reports.py +598 -0
  126. data/lib/subtrac/trac-plugins/worklogplugin/worklog/templates/worklog.html +45 -0
  127. data/lib/subtrac/trac-plugins/worklogplugin/worklog/templates/worklog_stop.html +70 -0
  128. data/lib/subtrac/trac-plugins/worklogplugin/worklog/templates/worklog_user.html +40 -0
  129. data/lib/subtrac/trac-plugins/worklogplugin/worklog/templates/worklog_webadminui.html +59 -0
  130. data/lib/subtrac/trac-plugins/worklogplugin/worklog/ticket_daemon.py +33 -0
  131. data/lib/subtrac/trac-plugins/worklogplugin/worklog/ticket_filter.py +153 -0
  132. data/lib/subtrac/trac-plugins/worklogplugin/worklog/timeline_hook.py +96 -0
  133. data/lib/subtrac/trac-plugins/worklogplugin/worklog/usermanual.py +29 -0
  134. data/lib/subtrac/trac-plugins/worklogplugin/worklog/util.py +31 -0
  135. data/lib/subtrac/trac-plugins/worklogplugin/worklog/webadminui.py +47 -0
  136. data/lib/subtrac/trac-plugins/worklogplugin/worklog/webui.py +174 -0
  137. data/lib/subtrac/trac-plugins/worklogplugin/worklog/xmlrpc.py +73 -0
  138. data/lib/subtrac/version.rb +4 -0
  139. metadata +191 -0
@@ -0,0 +1,86 @@
1
+ from datetime import timedelta
2
+ from estimationtools.utils import parse_options, execute_query, get_estimation_field, get_estimation_suffix, get_closed_states
3
+ from trac.util.html import Markup
4
+ from trac.wiki.macros import WikiMacroBase
5
+ import copy
6
+
7
+ DEFAULT_OPTIONS = {'width': '400', 'height': '100', 'color': 'ff9900'}
8
+
9
+ class WorkloadChart(WikiMacroBase):
10
+ """Creates workload chart for the selected tickets.
11
+
12
+ This macro creates a pie chart that shows the remaining estimated workload per ticket owner,
13
+ and the remaining work days.
14
+ It has the following parameters:
15
+ * a comma-separated list of query parameters for the ticket selection, in the form "key=value" as specified in TracQuery#QueryLanguage.
16
+ * `width`: width of resulting diagram (defaults to 400)
17
+ * `height`: height of resulting diagram (defaults to 100)
18
+ * `color`: color specified as 6-letter string of hexadecimal values in the format `RRGGBB`.
19
+ Defaults to `ff9900`, a nice orange.
20
+
21
+ Examples:
22
+ {{{
23
+ [[WorkloadChart(milestone=Sprint 1)]]
24
+ [[WorkloadChart(milestone=Sprint 1, width=600, height=100, color=00ff00)]]
25
+ }}}
26
+ """
27
+
28
+ estimation_field = get_estimation_field()
29
+ estimation_suffix = get_estimation_suffix()
30
+ closed_states = get_closed_states()
31
+
32
+ def render_macro(self, req, name, content):
33
+ db = self.env.get_db_cnx()
34
+ # prepare options
35
+ options, query_args = parse_options(db, content, copy.copy(DEFAULT_OPTIONS))
36
+
37
+ query_args[self.estimation_field + "!"] = None
38
+ tickets = execute_query(self.env, req, query_args)
39
+
40
+ sum = 0.0
41
+ estimations = {}
42
+ for ticket in tickets:
43
+ if ticket['status'] in self.closed_states:
44
+ continue
45
+ try:
46
+ estimation = float(ticket[self.estimation_field])
47
+ owner = ticket['owner']
48
+ sum += estimation
49
+ if estimations.has_key(owner):
50
+ estimations[owner] += estimation
51
+ else:
52
+ estimations[owner] = estimation
53
+ except:
54
+ pass
55
+
56
+ estimations_string = []
57
+ labels = []
58
+ for owner, estimation in estimations.iteritems():
59
+ labels.append("%s %s%s" % (owner, str(int(estimation)), self.estimation_suffix))
60
+ estimations_string.append(str(int(estimation)))
61
+
62
+ # Title
63
+ title = 'Workload'
64
+
65
+ # calculate remaining work time
66
+ if options.get('today') and options.get('enddate'):
67
+ currentdate = options['today']
68
+ day = timedelta(days=1)
69
+ days_remaining = 0
70
+ while currentdate <= options['enddate']:
71
+ if currentdate.weekday() < 5:
72
+ days_remaining += 1
73
+ currentdate += day
74
+ title += ' %s%s (%s workdays left)' % (int(sum), self.estimation_suffix, days_remaining)
75
+
76
+ return Markup("<img src=\"http://chart.apis.google.com/chart?"
77
+ "chs=%sx%s"
78
+ "&amp;chf=bg,s,00000000"
79
+ "&amp;chd=t:%s"
80
+ "&amp;cht=p3"
81
+ "&amp;chtt=%s"
82
+ "&amp;chl=%s"
83
+ "&amp;chco=%s\" "
84
+ "alt=\'Workload Chart\' />"
85
+ % (options['width'], options['height'], ",".join(estimations_string),
86
+ title, "|".join(labels), options['color']))
@@ -0,0 +1,20 @@
1
+ #!/usr/bin/env python
2
+ # -*- coding: iso-8859-1 -*-
3
+
4
+ from setuptools import setup
5
+
6
+ setup(
7
+ name = 'EstimationTools',
8
+ author = 'Joachim Hoessler',
9
+ author_email = 'hoessler@gmail.com',
10
+ description = 'Trac plugin for visualizing and quick editing of effort estimations',
11
+ version = '0.4',
12
+ license='BSD',
13
+ packages=['estimationtools'],
14
+ package_data = { 'estimationtools': ['htdocs/*.js', 'templates/*.html'] },
15
+ entry_points = {
16
+ 'trac.plugins': [
17
+ 'estimationtools = estimationtools'
18
+ ]
19
+ }
20
+ )
@@ -0,0 +1,23 @@
1
+ //javascript:(function(){var filter = function (fn, list, thisObj) { var arr = []; for (var i = 0; i < list.length; i++) { if (fn.call(thisObj, list[i])) { arr.push(list[i]);return arr;var sum = 0; var tds = filter(function(td){return td.innerHTML =='None';document.getElementsByTagName('td'),this); for(var i = 0; i < tds.length; i++){sum += parseFloat(tds[i].parentNode.childNodes[5].innerHTML);alert('Total hours: ' + sum);})();
2
+ javascript:(
3
+ function(){
4
+ var filter = function (fn, list, thisObj) {
5
+ var arr = [];
6
+ for (var i = 0; i < list.length; i++) {
7
+ if (fn.call(thisObj, list[i])) {
8
+ arr.push(list[i]);
9
+ }
10
+ }
11
+ return arr;
12
+ };
13
+ var sum = 0;
14
+ var tds = filter(function(td){
15
+ return td.innerHTML =='None';
16
+ },
17
+ document.getElementsByTagName('td'),this);
18
+ for(var i = 0; i < tds.length; i++){
19
+ sum += parseFloat(tds[i].parentNode.childNodes[5].innerHTML);
20
+ }
21
+ alert('Total hours: ' + sum);
22
+ }
23
+ )();
@@ -0,0 +1,128 @@
1
+ from pysqlite2 import dbapi2 as sqlite
2
+ from datetime import datetime, timedelta
3
+ from time import mktime
4
+ import os
5
+
6
+ tracDir = '/var/trac'
7
+ projectDBLocationFormat = '/var/trac/%s/db/trac.db'
8
+ # all directories in the trac directory
9
+ projects = [f for f in os.listdir(tracDir) if os.path.isdir('/'.join ([tracDir, f]))]
10
+
11
+ def makeDb(proj):
12
+ return projectDBLocationFormat % proj
13
+
14
+ def collectResultsFromAllTracs( sql ):
15
+ lst = []
16
+ for proj in projects:
17
+ try:
18
+ lst.extend([( proj , getResultSet( proj, sql ))])
19
+ except Exception, e:
20
+ print "collectResultsFromAllTracs: sql failed to execute on %s : %s " % (proj, e.args)
21
+
22
+ return lst
23
+
24
+ def executeAgainstAllTracs( sql ):
25
+ for proj in projects:
26
+ try:
27
+ executeNonQuery( proj, sql )
28
+ except:
29
+ print "executeAgainstAllTracs: sql failed to execute on %s" % proj
30
+
31
+
32
+ def executeNonQuery(proj, sql, *params):
33
+ """Executes the query on the given project"""
34
+ con = sqlite.connect(makeDb(proj))
35
+ cur = con.cursor()
36
+ try:
37
+ cur.execute(sql, params)
38
+ con.commit()
39
+ finally:
40
+ cur.close()
41
+ con.close()
42
+
43
+ def getColumnAsList(db, sql, col=0, *params):
44
+ return [valueList[col] for valueList in get_all(db, sql, *params)[1]]
45
+
46
+ def getScalar(proj , sql, col=0, *params):
47
+ db = sqlite.connect(makeDb(proj))
48
+ cur = db.cursor()
49
+ try:
50
+ cur.execute(sql, params)
51
+ data = cur.fetchone()
52
+ finally:
53
+ cur.close()
54
+ return data[col]
55
+
56
+
57
+ def getVector(proj, sql, *params):
58
+ db = sqlite.connect(makeDb(proj))
59
+ cur = db.cursor()
60
+ try:
61
+ cur.execute(sql, params)
62
+ data = cur.fetchone()
63
+ finally:
64
+ cur.close()
65
+ return data
66
+
67
+ def getAll(proj, sql, *params):
68
+ """Executes the query and returns the (description, data)"""
69
+ con = sqlite.connect(makeDb(proj))
70
+ cur = con.cursor()
71
+ try:
72
+ cur.execute(sql, params)
73
+ data = cur.fetchall()
74
+ desc = cur.description
75
+ finally:
76
+ cur.close()
77
+ con.close()
78
+ return (desc, data)
79
+
80
+ def getResultSet(proj, sql, *params):
81
+ """Executes the query and returns a Result Set"""
82
+ return ResultSet(getAll(proj, sql, *params))
83
+
84
+ def _columnName( columnDescription ):
85
+ """ given a the columnHeader from the result set from getAll gives you the column Headers """
86
+ return columnDescription[0];
87
+
88
+ class ResultSet:
89
+ """ the result of calling getResultSet """
90
+ def __init__ (self, (columnDescription, rows)):
91
+ self.columnDescription, self.rows = columnDescription, rows
92
+ self.columnNames = [_columnName(_) for _ in self.columnDescription]
93
+ self.columnMap = self.getColumnMap()
94
+
95
+ def getColumnMap ( self ):
96
+ """This function will take the result set from getAll and will
97
+ return a hash of the column names to their index """
98
+ h = {}
99
+ i = 0
100
+ if self.columnDescription:
101
+ for col in self.columnNames:
102
+ h[ col ] = i
103
+ i+=1
104
+ return h;
105
+
106
+ def value(self, col, row ):
107
+ """ given a row(list or idx) and a column( name or idx ), retrieve the appropriate value"""
108
+ tcol = type(col)
109
+ trow = type(row)
110
+ if tcol == str:
111
+ if(trow == list or trow == tuple):
112
+ return row[self.columnMap[col]]
113
+ elif(trow == int):
114
+ return self.rows[row][self.columnMap[col]]
115
+ else:
116
+ print ("rs.value Type Failed col:%s row:%s" % (type(col), type(row)))
117
+ elif tcol == int:
118
+ if(trow == list or trow == tuple):
119
+ return row[col]
120
+ elif(trow == int):
121
+ return self.rows[row][col]
122
+ else:
123
+ print ("rs.value Type Failed col:%s row:%s" % (type(col), type(row)))
124
+ else:
125
+ print ("rs.value Type Failed col:%s row:%s" % (type(col), type(row)))
126
+
127
+
128
+
@@ -0,0 +1,40 @@
1
+ #!/bin/sh
2
+ #
3
+ # An example hook script for the post-receive event
4
+ #
5
+ # This script is run after receive-pack has accepted a pack and the
6
+ # repository has been updated. It is passed arguments in through stdin
7
+ # in the form
8
+ # <oldrev> <newrev> <refname>
9
+ # For example:
10
+ # aa453216d1b3e49e7f6f98441fa56946ddcd6a20 68f7abf4e6f922807889f52bc043ecd31b79f814 refs/heads/master
11
+ #
12
+ # see contrib/hooks/ for an sample, or uncomment the next line (on debian)
13
+ #
14
+
15
+
16
+ TRAC_ENV="YOUR TRAC ENV HERE"
17
+ LOG="/dev/null"
18
+ echo "in git post commit: $TRAC_ENV" | cat >>$LOG
19
+
20
+ while read oval nval ref ; do
21
+ if expr "$oval" : '0*$' >/dev/null
22
+ then
23
+ git-rev-list "$nval"
24
+ else
25
+ git-rev-list "$nval" "^$oval"
26
+ fi | while read com ; do
27
+ echo "posting a comment to trac" | cat >>$LOG
28
+ /usr/bin/python /usr/share/trac/contrib/trac-post-commit.py \
29
+ -p "$TRAC_ENV" \
30
+ -r "$com" \
31
+ -u "$(git-rev-list -n 1 $com --pretty=format:%an | sed '1d')" \
32
+ -m "$(git-rev-list -n 1 $com --pretty=medium | sed '1,3d;s:^ ::')"
33
+ echo "DONE posting a comment to trac" | cat >>$LOG
34
+ done
35
+ done
36
+
37
+ echo "Done with trac commit hook: $TRAC_ENV" | cat >>$LOG
38
+
39
+ git reset --hard
40
+ echo "resetting repo working copy" | cat >>$LOG
@@ -0,0 +1,285 @@
1
+ #!/usr/bin/env python
2
+
3
+ # trac-post-commit-hook
4
+ # ----------------------------------------------------------------------------
5
+ # Copyright (c) 2004 Stephen Hansen
6
+ #
7
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
8
+ # of this software and associated documentation files (the "Software"), to
9
+ # deal in the Software without restriction, including without limitation the
10
+ # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
11
+ # sell copies of the Software, and to permit persons to whom the Software is
12
+ # furnished to do so, subject to the following conditions:
13
+ #
14
+ # The above copyright notice and this permission notice shall be included in
15
+ # all copies or substantial portions of the Software.
16
+ #
17
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20
+ # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22
+ # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
23
+ # IN THE SOFTWARE.
24
+ # ----------------------------------------------------------------------------
25
+
26
+ ### Changes for the Timing and Estimation plugin
27
+ #
28
+ # This script is very similar to "trac-post-commit" included with trac
29
+ # itself. This section explains functional changes relative to that
30
+ # script, and comments throughout the code explain other differences.
31
+ #
32
+ ## Logging support for debugging this hook
33
+ #
34
+ ## Support for specifying time spent in commit messages.
35
+ #
36
+ # "Blah refs #12 (1)" will add 1h to the spent time for issue #12
37
+ # "Blah refs #12 (spent 1.5)" will add 1h to the spent time for issue #12
38
+ #
39
+ # As above it is possible to use complicated messages:
40
+ #
41
+ # "Changed blah and foo to do this or that. Fixes #10 (1) and #12 (2),
42
+ # and refs #13 (0.5)."
43
+ #
44
+ # This will close #10 and #12, and add a note to #13 and also add 1h
45
+ # spent time to #10, add 2h spent time to #12 and add 30m spent time
46
+ # to #13.
47
+ #
48
+ # Note that:
49
+ # (spent 2), (sp 2) or simply (2) may be used for spent
50
+ # ' ', ',', '&' or 'and' may be used references
51
+
52
+ # This Subversion post-commit hook script is meant to interface to the
53
+ # Trac (http://www.edgewall.com/products/trac/) issue tracking/wiki/etc
54
+ # system.
55
+ #
56
+ # It should be called from the 'post-commit' script in Subversion, such as
57
+ # via:
58
+ #
59
+ # REPOS="$1"
60
+ # REV="$2"
61
+ # TRAC_ENV="/path/to/tracenv"
62
+ #
63
+ # /usr/bin/python /usr/local/src/trac/contrib/trac-post-commit-hook \
64
+ # -p "$TRAC_ENV" -r "$REV"
65
+ #
66
+ # (all the other arguments are now deprecated and not needed anymore)
67
+ #
68
+ # It searches commit messages for text in the form of:
69
+ # command #1
70
+ # command #1, #2
71
+ # command #1 & #2
72
+ # command #1 and #2
73
+ #
74
+ # Instead of the short-hand syntax "#1", "ticket:1" can be used as well, e.g.:
75
+ # command ticket:1
76
+ # command ticket:1, ticket:2
77
+ # command ticket:1 & ticket:2
78
+ # command ticket:1 and ticket:2
79
+ #
80
+ # In addition, the ':' character can be omitted and issue or bug can be used
81
+ # instead of ticket.
82
+ #
83
+ # You can have more then one command in a message. The following commands
84
+ # are supported. There is more then one spelling for each command, to make
85
+ # this as user-friendly as possible.
86
+ #
87
+ # close, closed, closes, fix, fixed, fixes
88
+ # The specified issue numbers are closed with the contents of this
89
+ # commit message being added to it.
90
+ # references, refs, addresses, re, see
91
+ # The specified issue numbers are left in their current status, but
92
+ # the contents of this commit message are added to their notes.
93
+ #
94
+ # A fairly complicated example of what you can do is with a commit message
95
+ # of:
96
+ #
97
+ # Changed blah and foo to do this or that. Fixes #10 and #12, and refs #12.
98
+ #
99
+ # This will close #10 and #12, and add a note to #12.
100
+
101
+ import re
102
+ import os
103
+ import sys
104
+ from datetime import datetime
105
+ from optparse import OptionParser
106
+
107
+ parser = OptionParser()
108
+ depr = '(not used anymore)'
109
+ parser.add_option('-e', '--require-envelope', dest='envelope', default='',
110
+ help="""
111
+ Require commands to be enclosed in an envelope.
112
+ If -e[], then commands must be in the form of [closes #4].
113
+ Must be two characters.""")
114
+ parser.add_option('-p', '--project', dest='project',
115
+ help='Path to the Trac project.')
116
+ parser.add_option('-r', '--revision', dest='rev',
117
+ help='Repository revision number.')
118
+ parser.add_option('-u', '--user', dest='user',
119
+ help='The user who is responsible for this action '+depr)
120
+ parser.add_option('-m', '--msg', dest='msg',
121
+ help='The log message to search '+depr)
122
+ parser.add_option('-c', '--encoding', dest='encoding',
123
+ help='The encoding used by the log message '+depr)
124
+ parser.add_option('-s', '--siteurl', dest='url',
125
+ help=depr+' the base_url from trac.ini will always be used.')
126
+
127
+ (options, args) = parser.parse_args(sys.argv[1:])
128
+
129
+ if not 'PYTHON_EGG_CACHE' in os.environ:
130
+ os.environ['PYTHON_EGG_CACHE'] = os.path.join(options.project, '.egg-cache')
131
+
132
+ from trac.env import open_environment
133
+ from trac.ticket.notification import TicketNotifyEmail
134
+ from trac.ticket import Ticket
135
+ from trac.ticket.web_ui import TicketModule
136
+ # TODO: move grouped_changelog_entries to model.py
137
+ from trac.util.text import to_unicode
138
+ from trac.util.datefmt import utc
139
+ from trac.versioncontrol.api import NoSuchChangeset
140
+
141
+ # Change logfile to point to someplace this script can write.
142
+ logfile = "/var/trac/commithook.log"
143
+ LOG = False
144
+
145
+ if LOG:
146
+ f = open (logfile,"w")
147
+ f.write("Begin Log\n")
148
+ f.close()
149
+ def log (s, *params):
150
+ f = open (logfile,"a")
151
+ f.write(s % params)
152
+ f.write("\n")
153
+ f.close()
154
+ else:
155
+ def log (s, *params):
156
+ pass
157
+
158
+ # Relative to trac standard, this table is hoisted out of class
159
+ # CommitHook so that it can be used in constructing a regexp that only
160
+ # matches on supported commands.
161
+ _supported_cmds = {'close': '_cmdClose',
162
+ 'closed': '_cmdClose',
163
+ 'closes': '_cmdClose',
164
+ 'fix': '_cmdClose',
165
+ 'fixed': '_cmdClose',
166
+ 'fixes': '_cmdClose',
167
+ 'addresses': '_cmdRefs',
168
+ 're': '_cmdRefs',
169
+ 'references': '_cmdRefs',
170
+ 'refs': '_cmdRefs',
171
+ 'see': '_cmdRefs'}
172
+
173
+ # Regexps are extended to include "(1)" and "(spent 1)".
174
+ ticket_prefix = '(?:#|(?:ticket|issue|bug)[: ]?)'
175
+ time_pattern = r'[ ]?(?:\((?:(?:spent|sp)[ ]?)?(-?[0-9]*(?:\.[0-9]+)?)\))?'
176
+ ticket_reference = ticket_prefix + '[0-9]+' + time_pattern
177
+ support_cmds_pattern = '|'.join(_supported_cmds.keys())
178
+
179
+ # Relative to upstream, only match command tokens (rather than
180
+ # matching all words).
181
+ ticket_command = (r'(?P<action>(?:%s))[ ]*'
182
+ '(?P<ticket>%s(?:(?:[, &]*|[ ]?and[ ]?)%s)*)' %
183
+ (support_cmds_pattern, ticket_reference, ticket_reference))
184
+
185
+ if options.envelope:
186
+ ticket_command = r'\%s%s\%s' % (options.envelope[0], ticket_command,
187
+ options.envelope[1])
188
+
189
+ # Because we build the regexp to recognize only supported commands,
190
+ # ignore case here.
191
+ command_re = re.compile(ticket_command, re.IGNORECASE)
192
+ ticket_re = re.compile(ticket_prefix + '([0-9]+)' + time_pattern, re.IGNORECASE)
193
+
194
+ class CommitHook:
195
+ def __init__(self, project=options.project, author=options.user,
196
+ rev=options.rev, url=options.url):
197
+ self.env = open_environment(project)
198
+ repos = self.env.get_repository()
199
+ repos.sync()
200
+
201
+ # Instead of bothering with the encoding, we'll use unicode data
202
+ # as provided by the Trac versioncontrol API (#1310).
203
+ try:
204
+ chgset = repos.get_changeset(rev)
205
+ except NoSuchChangeset:
206
+ return # out of scope changesets are not cached
207
+ self.author = chgset.author
208
+ self.rev = rev
209
+ self.msg = "(In [%s]) %s" % (rev, chgset.message)
210
+ self.now = datetime.now(utc)
211
+
212
+ cmd_groups = command_re.findall(self.msg)
213
+
214
+ log ("cmd_groups:%s", cmd_groups)
215
+ tickets = {}
216
+ # \todo Explain what xxx1 and xxx2 do; I can't see more params
217
+ # in command_re.
218
+ for cmd, tkts, xxx1, xxx2 in cmd_groups:
219
+ log ("cmd:%s, tkts%s ", cmd, tkts)
220
+ funcname = _supported_cmds.get(cmd.lower(), '')
221
+ if funcname:
222
+ for tkt_id, spent in ticket_re.findall(tkts):
223
+ func = getattr(self, funcname)
224
+ tickets.setdefault(tkt_id, []).append([func, spent])
225
+
226
+ for tkt_id, vals in tickets.iteritems():
227
+ log ("tkt_id:%s, vals%s ", tkt_id, vals)
228
+ spent_total = 0.0
229
+ try:
230
+ db = self.env.get_db_cnx()
231
+
232
+ ticket = Ticket(self.env, int(tkt_id), db)
233
+ for (cmd, spent) in vals:
234
+ cmd(ticket)
235
+ if spent:
236
+ spent_total += float(spent)
237
+
238
+ # determine sequence number...
239
+ cnum = 0
240
+ tm = TicketModule(self.env)
241
+ for change in tm.grouped_changelog_entries(ticket, db):
242
+ if change['permanent']:
243
+ cnum += 1
244
+
245
+ if spent_total:
246
+ self._setTimeTrackerFields(ticket, spent_total)
247
+ ticket.save_changes(self.author, self.msg, self.now, db, cnum+1)
248
+ db.commit()
249
+
250
+ tn = TicketNotifyEmail(self.env)
251
+ tn.notify(ticket, newticket=0, modtime=self.now)
252
+ except Exception, e:
253
+ # import traceback
254
+ # traceback.print_exc(file=sys.stderr)
255
+ log('Unexpected error while processing ticket ' \
256
+ 'ID %s: %s' % (tkt_id, e))
257
+ print>>sys.stderr, 'Unexpected error while processing ticket ' \
258
+ 'ID %s: %s' % (tkt_id, e)
259
+
260
+
261
+ def _cmdClose(self, ticket):
262
+ ticket['status'] = 'closed'
263
+ ticket['resolution'] = 'fixed'
264
+
265
+ def _cmdRefs(self, ticket):
266
+ pass
267
+
268
+ def _setTimeTrackerFields(self, ticket, spent):
269
+ log ("Setting ticket:%s spent: %s", ticket, spent)
270
+ if (spent != ''):
271
+ spentTime = float(spent)
272
+ # \bug If the ticket has not been modified since
273
+ # TimingAndEstimation was installed, then it might not
274
+ # have hours. It should still get hours applied because
275
+ # estimating and recording are separate.
276
+ if (ticket.values.has_key('hours')):
277
+ ticket['hours'] = str(spentTime)
278
+
279
+ if __name__ == "__main__":
280
+ if len(sys.argv) < 5:
281
+ print "For usage: %s --help" % (sys.argv[0])
282
+ print
283
+ print "Note that the deprecated options will be removed in Trac 0.12."
284
+ else:
285
+ CommitHook()