taskjuggler 3.7.1 → 3.7.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (336) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +18 -0
  3. data/Rakefile +4 -1
  4. data/data/tjp.vim +13 -13
  5. data/examples/ProjectTemplate/template.tjp +3 -3
  6. data/examples/Tutorial/tutorial.tjp +3 -3
  7. data/lib/taskjuggler/AppConfig.rb +1 -1
  8. data/lib/taskjuggler/BatchProcessor.rb +68 -57
  9. data/lib/taskjuggler/FileList.rb +1 -1
  10. data/lib/taskjuggler/MessageHandler.rb +0 -1
  11. data/lib/taskjuggler/ResourceScenario.rb +29 -1
  12. data/lib/taskjuggler/RuntimeConfig.rb +1 -1
  13. data/lib/taskjuggler/SheetHandlerBase.rb +5 -4
  14. data/lib/taskjuggler/StatusSheetReceiver.rb +2 -2
  15. data/lib/taskjuggler/StatusSheetSender.rb +1 -1
  16. data/lib/taskjuggler/TaskScenario.rb +7 -2
  17. data/lib/taskjuggler/TextParser/Scanner.rb +1 -1
  18. data/lib/taskjuggler/TimeSheetReceiver.rb +2 -2
  19. data/lib/taskjuggler/TimeSheetSender.rb +1 -1
  20. data/lib/taskjuggler/TimeSheets.rb +3 -2
  21. data/lib/taskjuggler/TjpSyntaxRules.rb +9 -3
  22. data/lib/taskjuggler/XMLDocument.rb +1 -1
  23. data/lib/taskjuggler/apps/Tj3Daemon.rb +2 -2
  24. data/lib/taskjuggler/apps/Tj3WebD.rb +1 -1
  25. data/lib/taskjuggler/daemon/ProjectServer.rb +2 -2
  26. data/lib/taskjuggler/reports/CSVFile.rb +1 -1
  27. data/lib/taskjuggler/reports/MspXmlRE.rb +5 -3
  28. data/lib/taskjuggler/reports/Report.rb +5 -5
  29. data/lib/taskjuggler/reports/TraceReport.rb +2 -2
  30. data/lib/taskjuggler/version.rb +1 -1
  31. data/man/tj3.1 +1 -1
  32. data/man/tj3client.1 +1 -1
  33. data/man/tj3d.1 +1 -1
  34. data/man/tj3man.1 +1 -1
  35. data/man/tj3ss_receiver.1 +1 -1
  36. data/man/tj3ss_sender.1 +2 -2
  37. data/man/tj3ts_receiver.1 +1 -1
  38. data/man/tj3ts_sender.1 +2 -2
  39. data/man/tj3ts_summary.1 +2 -2
  40. data/man/tj3webd.1 +1 -1
  41. data/manual/html/Day_To_Day_Juggling.html +1 -1
  42. data/manual/html/Getting_Started.html +1 -1
  43. data/manual/html/How_To_Contribute.html +1 -1
  44. data/manual/html/Installation.html +1 -1
  45. data/manual/html/Intro.html +1 -1
  46. data/manual/html/List_Attributes.html +1 -1
  47. data/manual/html/Reporting_Bugs.html +1 -1
  48. data/manual/html/Rich_Text_Attributes.html +1 -1
  49. data/manual/html/Software.html +1 -1
  50. data/manual/html/TaskJuggler_2x_Migration.html +1 -1
  51. data/manual/html/TaskJuggler_Internals.html +1 -1
  52. data/manual/html/The_TaskJuggler_Syntax.html +1 -1
  53. data/manual/html/Tutorial.html +1 -1
  54. data/manual/html/account.html +2 -2
  55. data/manual/html/account.task.html +1 -1
  56. data/manual/html/accountprefix.html +1 -1
  57. data/manual/html/accountreport.html +2 -2
  58. data/manual/html/accountroot.html +2 -2
  59. data/manual/html/active.html +1 -1
  60. data/manual/html/adopt.task.html +1 -1
  61. data/manual/html/aggregate.html +1 -1
  62. data/manual/html/alert.html +1 -1
  63. data/manual/html/alertlevels.html +1 -1
  64. data/manual/html/allocate.html +1 -1
  65. data/manual/html/alphabet.html +1 -1
  66. data/manual/html/alternative.html +1 -1
  67. data/manual/html/author.html +1 -1
  68. data/manual/html/auxdir.html +1 -1
  69. data/manual/html/auxdir.report.html +2 -2
  70. data/manual/html/balance.html +2 -2
  71. data/manual/html/booking.resource.html +1 -1
  72. data/manual/html/booking.task.html +1 -1
  73. data/manual/html/caption.html +2 -2
  74. data/manual/html/cellcolor.column.html +1 -1
  75. data/manual/html/celltext.column.html +1 -1
  76. data/manual/html/center.html +2 -2
  77. data/manual/html/charge.html +1 -1
  78. data/manual/html/chargeset.html +1 -1
  79. data/manual/html/columnid.html +5 -2
  80. data/manual/html/columns.html +2 -2
  81. data/manual/html/complete.html +1 -1
  82. data/manual/html/copyright.html +1 -1
  83. data/manual/html/credits.html +1 -1
  84. data/manual/html/currency.html +1 -1
  85. data/manual/html/currencyformat.html +2 -2
  86. data/manual/html/dailymax.html +1 -1
  87. data/manual/html/dailymin.html +1 -1
  88. data/manual/html/dailyworkinghours.html +1 -1
  89. data/manual/html/date.extend.html +1 -1
  90. data/manual/html/date.html +1 -1
  91. data/manual/html/definitions.html +1 -1
  92. data/manual/html/depends.html +1 -1
  93. data/manual/html/details.html +1 -1
  94. data/manual/html/disabled.html +1 -1
  95. data/manual/html/duration.html +1 -1
  96. data/manual/html/efficiency.html +1 -1
  97. data/manual/html/effort.html +1 -1
  98. data/manual/html/effortdone.html +1 -1
  99. data/manual/html/effortleft.html +1 -1
  100. data/manual/html/email.html +1 -1
  101. data/manual/html/enabled.html +1 -1
  102. data/manual/html/end.column.html +1 -1
  103. data/manual/html/end.html +1 -1
  104. data/manual/html/end.limit.html +1 -1
  105. data/manual/html/end.report.html +2 -2
  106. data/manual/html/end.timesheet.html +1 -1
  107. data/manual/html/endcredit.html +1 -1
  108. data/manual/html/epilog.html +2 -2
  109. data/manual/html/export.html +2 -2
  110. data/manual/html/extend.html +1 -1
  111. data/manual/html/fail.html +1 -1
  112. data/manual/html/fdl.html +1 -1
  113. data/manual/html/flags.account.html +1 -1
  114. data/manual/html/flags.html +1 -1
  115. data/manual/html/flags.journalentry.html +1 -1
  116. data/manual/html/flags.report.html +2 -2
  117. data/manual/html/flags.resource.html +1 -1
  118. data/manual/html/flags.statussheet.html +1 -1
  119. data/manual/html/flags.task.html +1 -1
  120. data/manual/html/flags.timesheet.html +1 -1
  121. data/manual/html/fontcolor.column.html +1 -1
  122. data/manual/html/footer.html +2 -2
  123. data/manual/html/formats.export.html +1 -1
  124. data/manual/html/formats.html +2 -2
  125. data/manual/html/functions.html +1 -1
  126. data/manual/html/gapduration.html +1 -1
  127. data/manual/html/gaplength.html +1 -1
  128. data/manual/html/halign.center.html +1 -1
  129. data/manual/html/halign.column.html +1 -1
  130. data/manual/html/halign.left.html +1 -1
  131. data/manual/html/halign.right.html +1 -1
  132. data/manual/html/hasalert.html +1 -1
  133. data/manual/html/header.html +2 -2
  134. data/manual/html/headline.html +2 -2
  135. data/manual/html/height.html +2 -2
  136. data/manual/html/hideaccount.html +2 -2
  137. data/manual/html/hidejournalentry.html +2 -2
  138. data/manual/html/hidereport.html +1 -1
  139. data/manual/html/hideresource.html +2 -2
  140. data/manual/html/hidetask.html +2 -2
  141. data/manual/html/icalreport.html +1 -1
  142. data/manual/html/include.macro.html +1 -1
  143. data/manual/html/include.project.html +1 -1
  144. data/manual/html/include.properties.html +1 -1
  145. data/manual/html/index.html +1 -1
  146. data/manual/html/inherit.extend.html +1 -1
  147. data/manual/html/interval1.html +1 -1
  148. data/manual/html/interval2.html +1 -1
  149. data/manual/html/interval3.html +1 -1
  150. data/manual/html/interval4.html +1 -1
  151. data/manual/html/isactive.html +1 -1
  152. data/manual/html/ischildof.html +1 -1
  153. data/manual/html/isdependencyof.html +1 -1
  154. data/manual/html/isdutyof.html +1 -1
  155. data/manual/html/isfeatureof.html +1 -1
  156. data/manual/html/isleaf.html +1 -1
  157. data/manual/html/ismilestone.html +1 -1
  158. data/manual/html/isongoing.html +1 -1
  159. data/manual/html/isresource.html +1 -1
  160. data/manual/html/isresponsibilityof.html +1 -1
  161. data/manual/html/istask.html +1 -1
  162. data/manual/html/isvalid.html +1 -1
  163. data/manual/html/journalattributes.html +2 -2
  164. data/manual/html/journalentry.html +1 -1
  165. data/manual/html/journalmode.html +2 -2
  166. data/manual/html/leaveallowance.html +1 -1
  167. data/manual/html/leaves.html +1 -1
  168. data/manual/html/left.html +2 -2
  169. data/manual/html/length.html +1 -1
  170. data/manual/html/limits.allocate.html +1 -1
  171. data/manual/html/limits.html +1 -1
  172. data/manual/html/limits.resource.html +1 -1
  173. data/manual/html/limits.task.html +1 -1
  174. data/manual/html/listitem.column.html +1 -1
  175. data/manual/html/listtype.column.html +1 -1
  176. data/manual/html/loadunit.html +2 -2
  177. data/manual/html/logicalexpression.html +1 -1
  178. data/manual/html/logicalflagexpression.html +1 -1
  179. data/manual/html/macro.html +1 -1
  180. data/manual/html/managers.html +1 -1
  181. data/manual/html/mandatory.html +1 -1
  182. data/manual/html/markdate.html +1 -1
  183. data/manual/html/maxend.html +1 -1
  184. data/manual/html/maximum.html +1 -1
  185. data/manual/html/maxstart.html +1 -1
  186. data/manual/html/milestone.html +1 -1
  187. data/manual/html/minend.html +1 -1
  188. data/manual/html/minimum.html +1 -1
  189. data/manual/html/minstart.html +1 -1
  190. data/manual/html/monthlymax.html +1 -1
  191. data/manual/html/monthlymin.html +1 -1
  192. data/manual/html/navbar.html +1 -1
  193. data/manual/html/navigator.html +1 -1
  194. data/manual/html/newtask.html +1 -1
  195. data/manual/html/nikureport.html +1 -1
  196. data/manual/html/note.task.html +1 -1
  197. data/manual/html/novevents.html +1 -1
  198. data/manual/html/now.html +1 -1
  199. data/manual/html/number.extend.html +1 -1
  200. data/manual/html/numberformat.html +2 -2
  201. data/manual/html/onend.html +1 -1
  202. data/manual/html/onstart.html +1 -1
  203. data/manual/html/opennodes.html +2 -2
  204. data/manual/html/outputdir.html +1 -1
  205. data/manual/html/overtime.booking.html +1 -1
  206. data/manual/html/period.column.html +1 -1
  207. data/manual/html/period.limit.html +1 -1
  208. data/manual/html/period.report.html +2 -2
  209. data/manual/html/period.task.html +1 -1
  210. data/manual/html/persistent.html +1 -1
  211. data/manual/html/precedes.html +1 -1
  212. data/manual/html/priority.html +1 -1
  213. data/manual/html/priority.timesheet.html +1 -1
  214. data/manual/html/project.html +1 -1
  215. data/manual/html/projectid.html +1 -1
  216. data/manual/html/projectid.task.html +1 -1
  217. data/manual/html/projectids.html +1 -1
  218. data/manual/html/projection.html +1 -1
  219. data/manual/html/prolog.html +2 -2
  220. data/manual/html/properties.html +1 -1
  221. data/manual/html/purge.html +2 -2
  222. data/manual/html/rate.html +1 -1
  223. data/manual/html/rate.resource.html +1 -1
  224. data/manual/html/rawhtmlhead.html +2 -2
  225. data/manual/html/reference.extend.html +1 -1
  226. data/manual/html/remaining.html +1 -1
  227. data/manual/html/replace.html +1 -1
  228. data/manual/html/reportprefix.html +1 -1
  229. data/manual/html/resource.html +1 -1
  230. data/manual/html/resourceattributes.html +1 -1
  231. data/manual/html/resourceprefix.html +1 -1
  232. data/manual/html/resourcereport.html +2 -2
  233. data/manual/html/resourceroot.html +2 -2
  234. data/manual/html/resources.limit.html +1 -1
  235. data/manual/html/responsible.html +1 -1
  236. data/manual/html/richtext.extend.html +1 -1
  237. data/manual/html/right.html +2 -2
  238. data/manual/html/rollupaccount.html +2 -2
  239. data/manual/html/rollupresource.html +2 -2
  240. data/manual/html/rolluptask.html +2 -2
  241. data/manual/html/scale.column.html +1 -1
  242. data/manual/html/scenario.html +1 -1
  243. data/manual/html/scenario.ical.html +1 -1
  244. data/manual/html/scenarios.export.html +1 -1
  245. data/manual/html/scenarios.html +2 -2
  246. data/manual/html/scenariospecific.extend.html +1 -1
  247. data/manual/html/scheduled.html +1 -1
  248. data/manual/html/scheduling.html +1 -1
  249. data/manual/html/schedulingmode.html +1 -1
  250. data/manual/html/select.html +1 -1
  251. data/manual/html/selfcontained.html +2 -2
  252. data/manual/html/shift.allocate.html +1 -1
  253. data/manual/html/shift.html +1 -1
  254. data/manual/html/shift.resource.html +1 -1
  255. data/manual/html/shift.task.html +1 -1
  256. data/manual/html/shift.timesheet.html +1 -1
  257. data/manual/html/shifts.allocate.html +1 -1
  258. data/manual/html/shifts.resource.html +1 -1
  259. data/manual/html/shifts.task.html +1 -1
  260. data/manual/html/shorttimeformat.html +1 -1
  261. data/manual/html/sloppy.booking.html +1 -1
  262. data/manual/html/sloppy.projection.html +1 -1
  263. data/manual/html/sortaccounts.html +2 -2
  264. data/manual/html/sortjournalentries.html +2 -2
  265. data/manual/html/sortresources.html +2 -2
  266. data/manual/html/sorttasks.html +2 -2
  267. data/manual/html/start.column.html +1 -1
  268. data/manual/html/start.html +1 -1
  269. data/manual/html/start.limit.html +1 -1
  270. data/manual/html/start.report.html +2 -2
  271. data/manual/html/startcredit.html +1 -1
  272. data/manual/html/status.statussheet.html +1 -1
  273. data/manual/html/status.timesheet.html +1 -1
  274. data/manual/html/statussheet.html +1 -1
  275. data/manual/html/statussheetreport.html +1 -1
  276. data/manual/html/strict.projection.html +1 -1
  277. data/manual/html/summary.html +1 -1
  278. data/manual/html/supplement.html +1 -1
  279. data/manual/html/supplement.resource.html +1 -1
  280. data/manual/html/supplement.task.html +1 -1
  281. data/manual/html/tagfile.html +1 -1
  282. data/manual/html/task.html +1 -1
  283. data/manual/html/task.statussheet.html +1 -1
  284. data/manual/html/task.timesheet.html +1 -1
  285. data/manual/html/taskattributes.html +1 -1
  286. data/manual/html/taskprefix.html +1 -1
  287. data/manual/html/taskreport.html +2 -2
  288. data/manual/html/taskroot.export.html +1 -1
  289. data/manual/html/taskroot.html +2 -2
  290. data/manual/html/text.extend.html +1 -1
  291. data/manual/html/textreport.html +2 -2
  292. data/manual/html/timeformat.html +2 -2
  293. data/manual/html/timeformat1.html +1 -1
  294. data/manual/html/timeformat2.html +1 -1
  295. data/manual/html/timeoff.nikureport.html +1 -1
  296. data/manual/html/timesheet.html +1 -1
  297. data/manual/html/timesheetreport.html +1 -1
  298. data/manual/html/timezone.export.html +1 -1
  299. data/manual/html/timezone.html +1 -1
  300. data/manual/html/timezone.report.html +2 -2
  301. data/manual/html/timezone.shift.html +1 -1
  302. data/manual/html/timingresolution.html +1 -1
  303. data/manual/html/title.column.html +1 -1
  304. data/manual/html/title.html +2 -2
  305. data/manual/html/toc.html +3 -3
  306. data/manual/html/tooltip.column.html +1 -1
  307. data/manual/html/tracereport.html +2 -2
  308. data/manual/html/trackingscenario.html +1 -1
  309. data/manual/html/treelevel.html +1 -1
  310. data/manual/html/vacation.html +1 -1
  311. data/manual/html/vacation.resource.html +1 -1
  312. data/manual/html/vacation.shift.html +1 -1
  313. data/manual/html/warn.html +1 -1
  314. data/manual/html/weeklymax.html +1 -1
  315. data/manual/html/weeklymin.html +1 -1
  316. data/manual/html/weekstartsmonday.html +1 -1
  317. data/manual/html/weekstartssunday.html +1 -1
  318. data/manual/html/width.column.html +1 -1
  319. data/manual/html/width.html +2 -2
  320. data/manual/html/work.html +1 -1
  321. data/manual/html/workinghours.project.html +1 -1
  322. data/manual/html/workinghours.resource.html +1 -1
  323. data/manual/html/workinghours.shift.html +1 -1
  324. data/manual/html/yearlyworkingdays.html +1 -1
  325. data/spec/TraceReport_spec.rb +1 -1
  326. data/spec/support/DaemonControl.rb +2 -3
  327. data/taskjuggler.gemspec +0 -3
  328. data/tasks/gem.rake +0 -1
  329. data/tasks/help2man.rake +1 -1
  330. data/tasks/manual.rake +1 -1
  331. data/test/TestSuite/CSV-Reports/quotes.tjp +20 -0
  332. data/test/TestSuite/CSV-Reports/refs/quotes.csv +5 -0
  333. data/test/TestSuite/Syntax/Correct/template.tjp +3 -3
  334. data/test/TestSuite/Syntax/Correct/tutorial.tjp +3 -3
  335. data/test/test_BatchProcessor.rb +6 -3
  336. metadata +7 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e5a0de8b9d1e062a746ba217051e7351d2481644f649f585528c7caabd6b69a9
4
- data.tar.gz: 6223c62cafa2db90ae8d4cc8759f5b5cff458b884833a4b6355284df450459c5
3
+ metadata.gz: ac8d1b5b2a3a8a3de01a39de2ef9533e1c86ade627b4a27ccf83427dac988093
4
+ data.tar.gz: 7dea4a421b72b1a6645b0699bfb4076eaa4fc46fcd1274066503dc2c36d7a343
5
5
  SHA512:
6
- metadata.gz: 70a76a0185eba07950375e0b44bcb32f74bada5b652d96f131fe4bf62cba6dabbd3d90b6f3216159e3d826836a74e228e1ef278b43f4bfbc6743c10aee41a48c
7
- data.tar.gz: 76324478980524c4c7a6be0039388d6116db7891037d179e094723c7ca74d7b19325c9668a0dc626e78e7b2346614a32b24a48aa53d1430c70773aa18a35c462
6
+ metadata.gz: a07a210795fb27f09a3a8cc09fcef2ceb21c0f08d47cedb8655b3cc1df8201b7f309278dd1464961a5c9e06164d12ae85f979435a3007701428fe852801ffccc
7
+ data.tar.gz: dd87f1321f59cbd9399a2b25ab7d5f3d16a01952579f3b54abfb7e2794a0f322c047e4bfb93434569eaea9cf1fd98a7ca6737ed20bea9e5c00816c6ab0f64bc4
data/CHANGELOG CHANGED
@@ -1,3 +1,21 @@
1
+ = Release 3.7.2 (2023-02-25)
2
+
3
+ == New Features
4
+
5
+ * The 'duties' column now supports the 'listitem' attribute.
6
+
7
+ == Bug Fixes
8
+
9
+ * File.exists? is no longer supported in Ruby 3.2.x
10
+ * Attempt to fix MS Project XML export for newer MSP versions.
11
+ * Eliminate use of useless variable
12
+ * Fix race condition that surfaces when using Ruby 3.x.
13
+ * Don't crash on division by zero for timesheets shorter than 1 week
14
+ * Properly escape double quotes in CSV file strings.
15
+ * Don't crash if task is overspeficied.
16
+ * Queries in listitems for some columns now respect scope property
17
+
18
+
1
19
  = Release 3.7.1 (2020-03-14)
2
20
 
3
21
  * Bumping version to 3.7.1
data/Rakefile CHANGED
@@ -4,10 +4,13 @@ $:.unshift File.join(File.dirname(__FILE__))
4
4
  lib = File.expand_path('../lib', __FILE__)
5
5
  $:.unshift lib unless $:.include?(lib)
6
6
 
7
+ require 'rake'
8
+ require 'rspec'
7
9
  require 'rake/clean'
10
+ require 'bundler/gem_tasks'
8
11
 
9
12
  Dir.glob( 'tasks/*.rake').each do |fn|
10
- begin
13
+ begin
11
14
  load fn;
12
15
  rescue LoadError
13
16
  puts "#{fn.split('/')[1]} tasks unavailable: #{$!}"
data/data/tjp.vim CHANGED
@@ -1,7 +1,7 @@
1
1
  " Vim syntax file
2
2
  " Language: TaskJuggler
3
3
  " Maintainer: TaskJuggler Developers <taskjuggler-devel@googlegroups.com>
4
- " Last Change: 2020-03-14 17:32:05 +0100
4
+ " Last Change: 2023-02-25 11:11:12 +0100
5
5
  " This file was automatically generated by VimSyntax.rb
6
6
 
7
7
  if exists("b:current_syntax")
@@ -21,6 +21,10 @@ syn keyword tjp_macro macro contained
21
21
  syn keyword tjp_project project contained
22
22
  syn keyword tjp_supplement supplement contained
23
23
 
24
+ syn keyword tjp_account account contained
25
+ hi def link tjp_account Function
26
+ syn keyword tjp_accountreport accountreport contained
27
+ hi def link tjp_accountreport Function
24
28
  syn keyword tjp_export export contained
25
29
  hi def link tjp_export Function
26
30
  syn keyword tjp_nikureport nikureport contained
@@ -47,11 +51,13 @@ syn keyword tjp_timesheetreport timesheetreport contained
47
51
  hi def link tjp_timesheetreport Function
48
52
  syn keyword tjp_tracereport tracereport contained
49
53
  hi def link tjp_tracereport Function
50
- syn keyword tjp_account account contained
51
- hi def link tjp_account Function
52
- syn keyword tjp_accountreport accountreport contained
53
- hi def link tjp_accountreport Function
54
54
 
55
+ syn keyword tjp_aggregate aggregate contained
56
+ hi def link tjp_aggregate Type
57
+ syn keyword tjp_credits credits contained
58
+ hi def link tjp_credits Type
59
+ syn keyword tjp_flags_account flags contained
60
+ hi def link tjp_flags_account Type
55
61
  syn keyword tjp_allocate allocate contained
56
62
  hi def link tjp_allocate Type
57
63
  syn keyword tjp_alternative alternative contained
@@ -646,12 +652,6 @@ syn keyword tjp_workinghours_resource workinghours contained
646
652
  hi def link tjp_workinghours_resource Type
647
653
  syn keyword tjp_workinghours_shift workinghours contained
648
654
  hi def link tjp_workinghours_shift Type
649
- syn keyword tjp_aggregate aggregate contained
650
- hi def link tjp_aggregate Type
651
- syn keyword tjp_credits credits contained
652
- hi def link tjp_credits Type
653
- syn keyword tjp_flags_account flags contained
654
- hi def link tjp_flags_account Type
655
655
 
656
656
  syn match tjparg contained /\${.*}/
657
657
  syn match tjpcomment /#.*$/
@@ -662,6 +662,8 @@ syn match tjpdate /\s\d\{4}-\d\{1,2}-\d\{1,2}\(-\d\{1,2}:\d\{1,2}\(:\d\{1,2}\)\?
662
662
  syn match tjptime /\s\d\{1,2}:\d\d\(:\d\d\)\?/
663
663
 
664
664
  syn cluster tjpcommon contains=tjpcomment,tjpdate,tjptime,tjpstring,tjpnumber
665
+ syn region tjpblk_account start=/^\s*account\s.*{\s*$/ end=/^\s*}\s*$/ transparent fold contains=@tjpcommon,tjp_account,tjp_account,tjpblk_account,tjp_aggregate,tjp_credits,tjp_flags_account
666
+ syn region tjpblk_accountreport start=/^\s*accountreport\s.*{\s*$/ end=/^\s*}\s*$/ transparent fold contains=@tjpcommon,tjp_accountreport,tjp_accountroot,tjp_auxdir_report,tjp_balance,tjp_caption,tjp_center,tjp_columns,tjpblk_columns,tjp_currencyformat,tjp_end_report,tjp_epilog,tjp_flags_report,tjp_footer,tjp_formats,tjp_header,tjp_headline,tjp_hidejournalentry,tjp_hideaccount,tjp_hideresource,tjp_hidetask,tjp_height,tjp_journalattributes,tjp_journalmode,tjp_left,tjp_loadunit,tjp_numberformat,tjp_opennodes,tjp_period_report,tjp_prolog,tjp_purge,tjp_rawhtmlhead,tjp_accountreport,tjpblk_accountreport,tjp_export,tjpblk_export,tjp_resourcereport,tjpblk_resourcereport,tjp_taskreport,tjpblk_taskreport,tjp_textreport,tjpblk_textreport,tjp_tracereport,tjpblk_tracereport,tjp_right,tjp_rollupaccount,tjp_rollupresource,tjp_rolluptask,tjp_scenarios,tjp_selfcontained,tjp_sortaccounts,tjp_sortjournalentries,tjp_sortresources,tjp_sorttasks,tjp_start_report,tjp_resourceroot,tjp_taskroot,tjp_timeformat,tjp_timezone_report,tjp_title,tjp_width
665
667
  syn region tjpblk_allocate start=/^\s*allocate\s.*{\s*$/ end=/^\s*}\s*$/ transparent contains=@tjpcommon,tjp_allocate,tjp_alternative,tjp_select,tjp_persistent,tjp_mandatory,tjp_shifts_allocate contained
666
668
  syn region tjpblk_export start=/^\s*export\s.*{\s*$/ end=/^\s*}\s*$/ transparent fold contains=@tjpcommon,tjp_export,tjp_definitions,tjp_formats_export,tjp_hideresource,tjp_hidetask,tjp_loadunit,tjp_purge,tjp_end_report,tjp_period_report,tjp_accountreport,tjpblk_accountreport,tjp_export,tjpblk_export,tjp_resourcereport,tjpblk_resourcereport,tjp_taskreport,tjpblk_taskreport,tjp_textreport,tjpblk_textreport,tjp_tracereport,tjpblk_tracereport,tjp_start_report,tjp_resourceattributes,tjp_rollupresource,tjp_rolluptask,tjp_scenarios_export,tjp_taskattributes,tjp_taskroot_export,tjp_timezone_export
667
669
  syn region tjpblk_date_extend start=/^\s*date\s.*{\s*$/ end=/^\s*}\s*$/ transparent contains=@tjpcommon,tjp_date_extend,tjp_inherit_extend,tjp_scenariospecific_extend contained
@@ -712,8 +714,6 @@ syn region tjpblk_task_timesheet start=/^\s*task\s.*{\s*$/ end=/^\s*}\s*$/ trans
712
714
  syn region tjpblk_timesheetreport start=/^\s*timesheetreport\s.*{\s*$/ end=/^\s*}\s*$/ transparent fold contains=@tjpcommon,tjp_timesheetreport,tjp_hideresource,tjp_hidetask,tjp_end_report,tjp_period_report,tjp_start_report,tjp_sortresources,tjp_sorttasks
713
715
  syn region tjpblk_tracereport start=/^\s*tracereport\s.*{\s*$/ end=/^\s*}\s*$/ transparent fold contains=@tjpcommon,tjp_tracereport,tjp_accountroot,tjp_auxdir_report,tjp_balance,tjp_caption,tjp_center,tjp_columns,tjpblk_columns,tjp_currencyformat,tjp_end_report,tjp_epilog,tjp_flags_report,tjp_footer,tjp_formats,tjp_header,tjp_headline,tjp_hidejournalentry,tjp_hideaccount,tjp_hideresource,tjp_hidetask,tjp_height,tjp_journalattributes,tjp_journalmode,tjp_left,tjp_loadunit,tjp_numberformat,tjp_opennodes,tjp_period_report,tjp_prolog,tjp_purge,tjp_rawhtmlhead,tjp_accountreport,tjpblk_accountreport,tjp_export,tjpblk_export,tjp_resourcereport,tjpblk_resourcereport,tjp_taskreport,tjpblk_taskreport,tjp_textreport,tjpblk_textreport,tjp_tracereport,tjpblk_tracereport,tjp_right,tjp_rollupaccount,tjp_rollupresource,tjp_rolluptask,tjp_scenarios,tjp_selfcontained,tjp_sortaccounts,tjp_sortjournalentries,tjp_sortresources,tjp_sorttasks,tjp_start_report,tjp_resourceroot,tjp_taskroot,tjp_timeformat,tjp_timezone_report,tjp_title,tjp_width
714
716
  syn region tjpblk_status_timesheet start=/^\s*status\s.*{\s*$/ end=/^\s*}\s*$/ transparent contains=@tjpcommon,tjp_status_timesheet,tjp_details,tjp_flags_timesheet,tjp_summary contained
715
- syn region tjpblk_account start=/^\s*account\s.*{\s*$/ end=/^\s*}\s*$/ transparent fold contains=@tjpcommon,tjp_account,tjp_account,tjpblk_account,tjp_aggregate,tjp_credits,tjp_flags_account
716
- syn region tjpblk_accountreport start=/^\s*accountreport\s.*{\s*$/ end=/^\s*}\s*$/ transparent fold contains=@tjpcommon,tjp_accountreport,tjp_accountroot,tjp_auxdir_report,tjp_balance,tjp_caption,tjp_center,tjp_columns,tjpblk_columns,tjp_currencyformat,tjp_end_report,tjp_epilog,tjp_flags_report,tjp_footer,tjp_formats,tjp_header,tjp_headline,tjp_hidejournalentry,tjp_hideaccount,tjp_hideresource,tjp_hidetask,tjp_height,tjp_journalattributes,tjp_journalmode,tjp_left,tjp_loadunit,tjp_numberformat,tjp_opennodes,tjp_period_report,tjp_prolog,tjp_purge,tjp_rawhtmlhead,tjp_accountreport,tjpblk_accountreport,tjp_export,tjpblk_export,tjp_resourcereport,tjpblk_resourcereport,tjp_taskreport,tjpblk_taskreport,tjp_textreport,tjpblk_textreport,tjp_tracereport,tjpblk_tracereport,tjp_right,tjp_rollupaccount,tjp_rollupresource,tjp_rolluptask,tjp_scenarios,tjp_selfcontained,tjp_sortaccounts,tjp_sortjournalentries,tjp_sortresources,tjp_sorttasks,tjp_start_report,tjp_resourceroot,tjp_taskroot,tjp_timeformat,tjp_timezone_report,tjp_title,tjp_width
717
717
  syn region tjpblk_macro start=/macro\s\+\h\w*\s*\[/ end=/\]$/ transparent fold contains=ALL
718
718
  syn region tjpstring start=/"/ skip=/\\"/ end=/"/
719
719
  syn region tjpstring start=/'/ skip=/\\'/ end=/'/
@@ -242,9 +242,9 @@ taskreport overview "" {
242
242
  # Macro to set the background color of a cell according to the alert
243
243
  # level of the task.
244
244
  macro AlertColor [
245
- cellcolor plan.alert = 0 "#00D000" # green
246
- cellcolor plan.alert = 1 "#D0D000" # yellow
247
- cellcolor plan.alert = 2 "#D00000" # red
245
+ cellcolor plan.alert = 0 "#90FF90" # green
246
+ cellcolor plan.alert = 1 "#FFFF90" # yellow
247
+ cellcolor plan.alert = 2 "#FF9090" # red
248
248
  ]
249
249
 
250
250
  taskreport status "" {
@@ -405,9 +405,9 @@ taskreport overview "" {
405
405
  # Macro to set the background color of a cell according to the alert
406
406
  # level of the task.
407
407
  macro AlertColor [
408
- cellcolor plan.alert = 0 "#00D000" # green
409
- cellcolor plan.alert = 1 "#D0D000" # yellow
410
- cellcolor plan.alert = 2 "#D00000" # red
408
+ cellcolor plan.alert = 0 "#90FF90" # green
409
+ cellcolor plan.alert = 1 "#FFFF90" # yellow
410
+ cellcolor plan.alert = 2 "#FF9090" # red
411
411
  ]
412
412
 
413
413
  taskreport status "" {
@@ -109,7 +109,7 @@ class AppConfig
109
109
  dirs = dataSearchDirs(baseDir)
110
110
  # Remove non-existing directories from the list again
111
111
  dirs.delete_if do |dir|
112
- !File.exist?(dir.untaint)
112
+ !File.exist?(dir)
113
113
  end
114
114
  dirs
115
115
  end
@@ -69,16 +69,16 @@ class TaskJuggler
69
69
  def initialize(maxCpuCores)
70
70
  @maxCpuCores = maxCpuCores
71
71
  # Jobs submitted by calling queue() are put in the @toRunQueue. The
72
- # pusher Thread will pick them up and fork them off into another
72
+ # launcher Thread will pick them up and fork them off into another
73
73
  # process.
74
- @toRunQueue = Queue.new
74
+ @toRunQueue = [ ]
75
75
  # A hash that maps the JobInfo objects of running jobs by their PID.
76
76
  @runningJobs = { }
77
77
  # A list of jobs that wait to complete their writing.
78
78
  @spoolingJobs = [ ]
79
79
  # The wait() method will then clean the @toDropQueue, executes the post
80
80
  # processing block and removes all JobInfo related objects.
81
- @toDropQueue = Queue.new
81
+ @toDropQueue = []
82
82
 
83
83
  # A semaphore to guard accesses to @runningJobs, @spoolingJobs and
84
84
  # following shared data structures.
@@ -106,28 +106,34 @@ class TaskJuggler
106
106
  # to identify the job upon completion. +block+ is a Ruby code block to be
107
107
  # executed in a separate process.
108
108
  def queue(tag = nil, &block)
109
- raise 'You cannot call queue() while wait() is running!' if @jobsOut > 0
110
-
111
- # If this is the first queued job for this run, we have to start the
112
- # helper threads.
113
- if @jobsIn == 0
114
- # The JobInfo objects in the @toRunQueue are processed by the pusher
115
- # thread. It forkes off processes to execute the code block associated
116
- # with the JobInfo.
117
- @pusher = Thread.new { pusher }
118
- # The popper thread waits for terminated childs and picks up the
119
- # results.
120
- @popper = Thread.new { popper }
121
- # The grabber thread collects $stdout and $stderr data from each child
122
- # process and stores them in the corresponding JobInfo.
123
- @grabber = Thread.new { grabber }
124
- end
125
109
 
126
110
  # Create a new JobInfo object for the job and push it to the @toRunQueue.
127
- job = JobInfo.new(@jobsIn, block, tag)
128
- # Increase job counter
129
- @lock.synchronize { @jobsIn += 1 }
130
- @toRunQueue.push(job)
111
+ @lock.synchronize do
112
+ raise 'You cannot call queue() while wait() is running!' if @jobsOut > 0
113
+
114
+ # If this is the first queued job for this run, we have to start the
115
+ # helper threads.
116
+ if @jobsIn == 0
117
+ # The JobInfo objects in the @toRunQueue are processed by the
118
+ # launcher thread. It forkes off processes to execute the code
119
+ # block associated with the JobInfo.
120
+ @launcher = Thread.new { launcher }
121
+ # The receiver thread waits for terminated child processes and picks
122
+ # up the results.
123
+ @receiver = Thread.new { receiver }
124
+ # The grabber thread collects $stdout and $stderr data from each
125
+ # child process and stores them in the corresponding JobInfo.
126
+ @grabber = Thread.new { grabber }
127
+ end
128
+
129
+ # To track a job through the queues, we use a JobInfo object to hold
130
+ # all data associated with a job.
131
+ job = JobInfo.new(@jobsIn, block, tag)
132
+ # Increase job counter
133
+ @jobsIn += 1
134
+ # Push the job to the toRunQueue.
135
+ @toRunQueue.push(job)
136
+ end
131
137
  end
132
138
 
133
139
  # Wait for all jobs to complete. The code block will get the JobInfo
@@ -138,29 +144,27 @@ class TaskJuggler
138
144
 
139
145
  # When we have received as many jobs in the @toDropQueue than we have
140
146
  # started then we're done.
141
- while !@lock.synchronize { @jobsIn == @jobsOut }
142
- if @toDropQueue.empty?
143
- sleep(@timeout)
144
- else
145
- # We have completed jobs.
146
- while !@toDropQueue.empty?
147
- # Pop a job from the @toDropQueue and call the block with it.
148
- job = @toDropQueue.pop
149
- # Remove the job related entries from the housekeeping tables.
150
- @lock.synchronize { @jobsOut += 1 }
151
-
147
+ while @lock.synchronize { @jobsOut < @jobsIn }
148
+ job = nil
149
+ @lock.synchronize do
150
+ if !@toDropQueue.empty? && (job = @toDropQueue.pop)
152
151
  # Call the post-processing block that was passed to wait() with
153
152
  # the JobInfo object as argument.
153
+ @jobsOut += 1
154
154
  yield(job)
155
155
  end
156
156
  end
157
+
158
+ unless job
159
+ sleep(@timeout)
160
+ end
157
161
  end
158
162
 
159
163
  # Signal threads to stop
160
164
  @terminate = true
161
165
  # Wait for treads to finish
162
- @pusher.join
163
- @popper.join
166
+ @launcher.join
167
+ @receiver.join
164
168
  @grabber.join
165
169
 
166
170
  # Reset some variables so we can reuse the object for further job runs.
@@ -175,25 +179,22 @@ class TaskJuggler
175
179
 
176
180
  # This function runs in a separate thread to pop JobInfo items from the
177
181
  # @toRunQueue and create child processes for them.
178
- def pusher
182
+ def launcher
179
183
  # Run until the terminate flag is set.
180
184
  until @terminate
181
- if @toRunQueue.empty? ||
182
- @lock.synchronize{ @runningJobs.length >= @maxCpuCores }
185
+ job = nil
186
+ unless @lock.synchronize { @runningJobs.length < @maxCpuCores &&
187
+ (job = @toRunQueue.pop) }
183
188
  # We have no jobs in the @toRunQueue or all CPU cores in use already.
184
189
  sleep(@timeout)
185
190
  else
186
191
  @lock.synchronize do
187
- # Get a new job from the @toRunQueue
188
- job = @toRunQueue.pop
189
-
190
192
  job.openPipes
191
- # Add the receiver end of the pipe to the @pipes Array.
193
+ # Add the receiver end of the pipe to the pipes Arrays.
192
194
  @pipes << job.stdoutP
195
+ @pipes << job.stderrP
193
196
  # Map the pipe end to this JobInfo object.
194
197
  @pipeToJob[job.stdoutP] = job
195
- # Same for $stderr.
196
- @pipes << job.stderrP
197
198
  @pipeToJob[job.stderrP] = job
198
199
 
199
200
  pid = fork do
@@ -224,15 +225,20 @@ class TaskJuggler
224
225
 
225
226
  # This function runs in a separate thread to wait for completed jobs. It
226
227
  # waits for the process completion and stores the result in the
227
- # corresponding JobInfo object.
228
- def popper
228
+ # corresponding JobInfo object. Aborted jobs are pushed to the
229
+ # @toDropQueue while completed jobs are pushed to the @spoolingJobs queue.
230
+ def receiver
229
231
  until @terminate
230
- if @runningJobs.empty?
231
- # No pending jobs, wait a bit.
232
- sleep(@timeout)
233
- else
232
+ pid = retVal = nil
233
+ begin
234
234
  # Wait for the next job to complete.
235
235
  pid, retVal = Process.wait2
236
+ rescue Errno::ECHILD
237
+ # No running jobs. Wait a bit.
238
+ sleep(@timeout)
239
+ end
240
+
241
+ if pid && retVal
236
242
  job = nil
237
243
  @lock.synchronize do
238
244
  # Get the JobInfo object that corresponds to the process ID. The
@@ -242,7 +248,7 @@ class TaskJuggler
242
248
  # Remove the job from the @runningJobs Hash.
243
249
  @runningJobs.delete(pid)
244
250
  # Save the return value.
245
- job.retVal = retVal.dup
251
+ job.retVal = retVal.exitstatus
246
252
  if retVal.signaled?
247
253
  cleanPipes(job)
248
254
  # Aborted jobs will probably not send an EOT. So we fastrack
@@ -269,22 +275,27 @@ class TaskJuggler
269
275
  res = nil
270
276
  begin
271
277
  @lock.synchronize do
272
- if (res = select(@pipes, nil, @pipes, @timeout))
278
+ if (res = IO.select(@pipes, nil, nil, @timeout))
273
279
  # We have output data from at least one child. Check which pipe
274
280
  # actually triggered the select.
275
281
  res[0].each do |pipe|
276
282
  # Find the corresponding JobInfo object.
277
283
  job = @pipeToJob[pipe]
278
- # Store the output.
284
+
285
+ # Store the standard output.
279
286
  if pipe == job.stdoutP
280
287
  # Look for the EOT character to signal the end of the text.
281
- if (c = pipe.getc) == ?\004
288
+ if pipe.closed? || (c = pipe.read_nonblock(1)) == ?\004
282
289
  job.stdoutEOT = true
283
290
  else
284
291
  job.stdout << c
285
292
  end
286
- else
287
- if (c = pipe.getc) == ?\004
293
+ end
294
+
295
+ # Store the error output.
296
+ if pipe == job.stderrP
297
+ # Look for the EOT character to signal the end of the text.
298
+ if pipe.closed? || (c = pipe.read_nonblock(1)) == ?\004
288
299
  job.stderrEOT = true
289
300
  else
290
301
  job.stderr << c
@@ -17,7 +17,7 @@ class TaskJuggler
17
17
  class FileRecord
18
18
 
19
19
  def initialize(fileName)
20
- @name = fileName.dup.untaint
20
+ @name = fileName.dup
21
21
  @mtime = File.mtime(@name)
22
22
  end
23
23
 
@@ -248,7 +248,6 @@ class TaskJuggler
248
248
 
249
249
  timeStamp = Time.new.strftime("%Y-%m-%d %H:%M:%S")
250
250
  begin
251
- @logFile.untaint
252
251
  File.open(@logFile, 'a') do |f|
253
252
  f.write("#{timeStamp} #{type} #{@appName}[#{Process.pid}]: " +
254
253
  "#{message}\n")
@@ -3,7 +3,7 @@
3
3
  #
4
4
  # = ResourceScenario.rb -- The TaskJuggler III Project Management Software
5
5
  #
6
- # Copyright (c) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014
6
+ # Copyright (c) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2020
7
7
  # by Chris Schlaeger <cs@taskjuggler.org>
8
8
  #
9
9
  # This program is free software; you can redistribute it and/or modify
@@ -322,6 +322,34 @@ class TaskJuggler
322
322
  end
323
323
  end
324
324
 
325
+ # A list of the tasks that the resource has been allocated to work on in
326
+ # the report time frame.
327
+ def query_duties(query)
328
+ list = []
329
+ iv = TimeInterval.new(query.start, query.end)
330
+ @duties.each do |task|
331
+ if task.hasResourceAllocated?(@scenarioIdx, iv, @property)
332
+ if query.listItem
333
+ rti = RichText.new(query.listItem, RTFHandlers.create(@project)).
334
+ generateIntermediateFormat
335
+ unless rti
336
+ error('bad_resource_ts_query',
337
+ "Syntax error in query statement for task attribute " +
338
+ "'resources'.")
339
+ end
340
+ q = query.dup
341
+ q.property = task
342
+ q.scopeProperty = @property
343
+ rti.setQuery(q)
344
+ list << "<nowiki>#{rti.to_s}</nowiki>"
345
+ else
346
+ list << "<nowiki>#{task.name} (#{task.id})</nowiki>"
347
+ end
348
+ end
349
+ end
350
+ query.assignList(list)
351
+ end
352
+
325
353
  # The effort allocated to the Resource in the specified interval. In case a
326
354
  # Task is given as scope property only the effort allocated to this Task is
327
355
  # taken into account.
@@ -48,7 +48,7 @@ class RuntimeConfig
48
48
  return false unless (p = @config)
49
49
  sections.each do |sec|
50
50
  p = p['_' + sec]
51
- unless p
51
+ unless p && p.is_a?(Hash)
52
52
  debug("Section #{section} not found in config file")
53
53
  return false
54
54
  end
@@ -166,11 +166,12 @@ class TaskJuggler
166
166
  inReplyTo = nil)
167
167
  case @emailDeliveryMethod
168
168
  when 'smtp'
169
- Mail.defaults do
170
- delivery_method :smtp, {
169
+ settings_dto = {
171
170
  :address => @smtpServer,
172
- :port => 25
173
- }
171
+ :port => 25,
172
+ }
173
+ Mail.defaults do
174
+ delivery_method :smtp, settings_dto
174
175
  end
175
176
  when 'sendmail'
176
177
  Mail.defaults do
@@ -35,9 +35,9 @@ class TaskJuggler
35
35
  @logFile = 'statussheets.log'
36
36
 
37
37
  # Regular expression to identify status sheets.
38
- @sheetHeader = /^[ ]*statussheet\s([a-z][a-z0-9_]*)\s[0-9\-:+]*\s-\s([0-9]*-[0-9]*-[0-9]*)/
38
+ @sheetHeader = /^[ ]*statussheet\s([a-zA-Z_][a-zA-Z0-9_]*)\s[0-9\-:+]*\s-\s([0-9]*-[0-9]*-[0-9]*)/
39
39
  # Regular expression to extract the sheet signature (time period).
40
- @signatureFilter = /^[ ]*statussheet\s[a-z][a-z0-9_]*\s([0-9:\-+]*\s-\s[0-9:\-+]*)/
40
+ @signatureFilter = /^[ ]*statussheet\s[a-zA-Z_][a-zA-Z0-9_]*\s([0-9:\-+]*\s-\s[0-9:\-+]*)/
41
41
  @emailSubject = "Status report from %s for %s"
42
42
  end
43
43
 
@@ -39,7 +39,7 @@ class TaskJuggler
39
39
  # The log file
40
40
  @logFile = 'statussheets.log'
41
41
 
42
- @signatureFilter = /^[ ]*statussheet\s[a-z][a-z0-9_]*\s([0-9:\-+]*\s-\s[0-9:\-+]*)/
42
+ @signatureFilter = /^[ ]*statussheet\s[a-zA-Z_][a-zA-Z0-9_]*\s([0-9:\-+]*\s-\s[0-9:\-+]*)/
43
43
  @introText = <<'EOT'
44
44
  Please find enclosed your weekly status report template. Please fill out the
45
45
  form and send it back to the sender of this email. You can either use the
@@ -1508,6 +1508,7 @@ class TaskJuggler
1508
1508
  end
1509
1509
  q = query.dup
1510
1510
  q.property = resource
1511
+ q.scopeProperty = @property
1511
1512
  rti.setQuery(q)
1512
1513
  list << "<nowiki>#{rti.to_s}</nowiki>"
1513
1514
  else
@@ -2179,8 +2180,12 @@ class TaskJuggler
2179
2180
  # been set already.
2180
2181
  if @scheduled && @effort == 0 && @length == 0 && @duration == 0 &&
2181
2182
  !@milestone
2182
- @start = @project.idxToDate(firstSlotIdx) unless @start
2183
- @end = @project.idxToDate(lastSlotIdx + 1) unless @end
2183
+ unless @start || !firstSlotIdx
2184
+ @start = @project.idxToDate(firstSlotIdx)
2185
+ end
2186
+ unless @end || !lastSlotIdx
2187
+ @end = @project.idxToDate(lastSlotIdx + 1)
2188
+ end
2184
2189
  end
2185
2190
  end
2186
2191
 
@@ -169,7 +169,7 @@ class TaskJuggler::TextParser
169
169
 
170
170
  def initialize(fileName, log, textScanner)
171
171
  super(log, textScanner)
172
- @fileName = fileName.dup.untaint
172
+ @fileName = fileName.dup
173
173
  data = (fileName == '.' ? $stdin : File.new(@fileName, 'r')).read
174
174
  begin
175
175
  @stream = StringIO.new(data.forceUTF8Encoding)
@@ -32,9 +32,9 @@ class TaskJuggler
32
32
  @logFile = 'timesheets.log'
33
33
 
34
34
  # Regular expression to identify time sheets.
35
- @sheetHeader = /^[ ]*timesheet\s([a-z][a-z0-9_]*)\s[0-9\-:+]*\s-\s([0-9]*-[0-9]*-[0-9]*)/
35
+ @sheetHeader = /^[ ]*timesheet\s([a-zA-Z_][a-zA-Z0-9_]*)\s[0-9\-:+]*\s-\s([0-9]*-[0-9]*-[0-9]*)/
36
36
  # Regular expression to extract the sheet signature (time period).
37
- @signatureFilter = /^[ ]*timesheet\s[a-z][a-z0-9_]*\s([0-9:\-+]*\s-\s[0-9:\-+]*)/
37
+ @signatureFilter = /^[ ]*timesheet\s[a-zA-Z_][a-zA-Z0-9_]*\s([0-9:\-+]*\s-\s[0-9:\-+]*)/
38
38
  @emailSubject = "Report from %s for %s"
39
39
  end
40
40
 
@@ -38,7 +38,7 @@ class TaskJuggler
38
38
  # The log file
39
39
  @logFile = 'timesheets.log'
40
40
 
41
- @signatureFilter = /^[ ]*timesheet\s[a-z][a-z0-9_]*\s([0-9:\-+]*\s-\s[0-9:\-+]*)/
41
+ @signatureFilter = /^[ ]*timesheet\s[a-zA-Z_][a-zA-Z0-9_]*\s([0-9:\-+]*\s-\s[0-9:\-+]*)/
42
42
  @introText = <<'EOT'
43
43
  Please find enclosed your weekly report template. Please fill out
44
44
  the form and send it back to the sender of this email. You can either
@@ -325,9 +325,10 @@ class TaskJuggler
325
325
  def totalGrossWorkingSlots
326
326
  project = @resource.project
327
327
  # Calculate the number of weeks in the report
328
- weeksToReport = (@interval.end - @interval.start) / (60 * 60 * 24 * 7)
328
+ weeksToReport = (@interval.end - @interval.start).to_f /
329
+ (60 * 60 * 24 * 7)
329
330
 
330
- daysToSlots(project.weeklyWorkingDays * weeksToReport)
331
+ daysToSlots((project.weeklyWorkingDays * weeksToReport).to_i)
331
332
  end
332
333
 
333
334
  # Compute the total number of actual working time slots of the
@@ -3,7 +3,7 @@
3
3
  #
4
4
  # = TjpSyntaxRules.rb -- The TaskJuggler III Project Management Software
5
5
  #
6
- # Copyright (c) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014
6
+ # Copyright (c) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2020
7
7
  # by Chris Schlaeger <cs@taskjuggler.org>
8
8
  #
9
9
  # This program is free software; you can redistribute it and/or modify
@@ -673,7 +673,7 @@ EOT
673
673
  def rule_color
674
674
  pattern(%w( $STRING ), lambda {
675
675
  col = @val[0]
676
- unless /#[0-9A-Fa-f]{3}/ =~ col || /#[0-9A-Fa-f]{3}/ =~ col
676
+ unless /#[0-9A-Fa-f]{3}/ =~ col || /#[0-9A-Fa-f]{6}/ =~ col
677
677
  error('bad_color',
678
678
  "Color values must be specified as '#RGB' or '#RRGGBB' values",
679
679
  @sourceFileInfo[0])
@@ -3932,7 +3932,13 @@ EOT
3932
3932
  descr('The duration of a task')
3933
3933
 
3934
3934
  singlePattern('_duties')
3935
- descr('List of tasks that the resource is allocated to')
3935
+ descr(<<'EOT'
3936
+ List of tasks that the resource is allocated to
3937
+
3938
+ The list can be customized by the [[listitem.column|listitem]] and
3939
+ [[listtype.column|listtype]] attribute.
3940
+ EOT
3941
+ )
3936
3942
 
3937
3943
  singlePattern('_efficiency')
3938
3944
  descr('Measure for how efficient a resource can perform tasks')
@@ -52,7 +52,7 @@ class TaskJuggler
52
52
 
53
53
  # Write the XMLDocument to the specified file.
54
54
  def write(filename)
55
- f = filename == '.' ? $stdout : File.new(filename.untaint, 'w')
55
+ f = filename == '.' ? $stdout : File.new(filename, 'w')
56
56
  @elements.each do |element|
57
57
  f.puts element.to_s(0)
58
58
  end
@@ -37,7 +37,7 @@ class TaskJuggler
37
37
  @port = nil
38
38
  @webServer = false
39
39
  @webServerPort = 8080
40
- @webdPidFile = File.join(Dir.getwd, ".tj3webd-#{$$}.pid").untaint
40
+ @webdPidFile = File.join(Dir.getwd, ".tj3webd-#{$$}.pid")
41
41
  end
42
42
 
43
43
  def processArguments(argv)
@@ -92,7 +92,7 @@ EOT
92
92
  # Set some config variables if corresponding data was provided via the
93
93
  # command line.
94
94
  broker.port = @port if @port
95
- broker.uriFile = @uriFile.untaint
95
+ broker.uriFile = @uriFile
96
96
  broker.projectFiles = sortInputFiles(files) unless files.empty?
97
97
  broker.daemonize = @daemonize
98
98
  # Create log files for standard IO for each child process if the daemon
@@ -89,7 +89,7 @@ EOT
89
89
  # Set some config variables if corresponding data was provided via the
90
90
  # command line.
91
91
  webServer.port = @port if @port
92
- webServer.uriFile = @uriFile.untaint
92
+ webServer.uriFile = @uriFile
93
93
  webServer.webServerPort = @webServerPort if @webServerPort
94
94
  webServer.daemonize = @daemonize
95
95
  webServer.pidFile = @pidFile
@@ -137,9 +137,9 @@ class TaskJuggler
137
137
  # directory. The second one is the master project file (.tjp file).
138
138
  # Additionally a list of optional .tji files can be provided.
139
139
  def loadProject(args)
140
- dirAndFiles = args.dup.untaint
140
+ dirAndFiles = args.dup
141
141
  # The first argument is the working directory
142
- Dir.chdir(args.shift.untaint)
142
+ Dir.chdir(args.shift)
143
143
 
144
144
  # Save a time stamp of when the project file loading started.
145
145
  @modifiedCheck = TjTime.new