Run of fresh-snapshots for tj3

Try this locally (using silver-platter):

debian-svp new-upstream --snapshot tj3 

Merge these changes:

git pull https://janitor.debian.net/git/tj3 fresh-snapshots/main
git pull https://janitor.debian.net/git/tj3 fresh-snapshots/pristine-tar
git pull https://janitor.debian.net/git/tj3 fresh-snapshots/upstream

Summary

Merged new upstream version: 3.7.1+git20200830.1.8198281 (was: 3.7.1).

Diff

Branch: main

diff --git a/debian/changelog b/debian/changelog
index ddcefa40..fdacd7e4 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,6 @@
+tj3 (3.7.1+git20200830.1.8198281-1) UNRELEASED; urgency=low
+ -- Debian Janitor <janitor@jelmer.uk>  Mon, 05 Apr 2021 10:14:06 -0000
+
 tj3 (3.7.1-1) unstable; urgency=medium
 
   [ Vincent Bernat ]
diff --git a/lib/taskjuggler/ResourceScenario.rb b/lib/taskjuggler/ResourceScenario.rb
index c6388ae2..b45e749e 100644
--- a/lib/taskjuggler/ResourceScenario.rb
+++ b/lib/taskjuggler/ResourceScenario.rb
@@ -3,7 +3,7 @@
 #
 # = ResourceScenario.rb -- The TaskJuggler III Project Management Software
 #
-# Copyright (c) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014
+# Copyright (c) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2020
 #               by Chris Schlaeger <cs@taskjuggler.org>
 #
 # This program is free software; you can redistribute it and/or modify
@@ -322,6 +322,34 @@ class TaskJuggler
       end
     end
 
+    # A list of the tasks that the resource has been  allocated to work on in
+    # the report time frame.
+    def query_duties(query)
+      list = []
+      iv = TimeInterval.new(query.start, query.end)
+      @duties.each do |task|
+        if task.hasResourceAllocated?(@scenarioIdx, iv, @property)
+          if query.listItem
+            rti = RichText.new(query.listItem, RTFHandlers.create(@project)).
+              generateIntermediateFormat
+            unless rti
+              error('bad_resource_ts_query',
+                    "Syntax error in query statement for task attribute " +
+                    "'resources'.")
+            end
+            q = query.dup
+            q.property = task
+            q.scopeProperty = @property
+            rti.setQuery(q)
+            list << "<nowiki>#{rti.to_s}</nowiki>"
+          else
+            list << "<nowiki>#{task.name} (#{task.id})</nowiki>"
+          end
+        end
+      end
+      query.assignList(list)
+    end
+
     # The effort allocated to the Resource in the specified interval. In case a
     # Task is given as scope property only the effort allocated to this Task is
     # taken into account.
diff --git a/lib/taskjuggler/RuntimeConfig.rb b/lib/taskjuggler/RuntimeConfig.rb
index 386b46d7..d6dd1636 100644
--- a/lib/taskjuggler/RuntimeConfig.rb
+++ b/lib/taskjuggler/RuntimeConfig.rb
@@ -48,7 +48,7 @@ class RuntimeConfig
     return false unless (p = @config)
     sections.each do |sec|
       p = p['_' + sec]
-      unless p
+      unless p && p.is_a?(Hash)
         debug("Section #{section} not found in config file")
         return false
       end
diff --git a/lib/taskjuggler/TaskScenario.rb b/lib/taskjuggler/TaskScenario.rb
index d54b2d4c..392d68df 100644
--- a/lib/taskjuggler/TaskScenario.rb
+++ b/lib/taskjuggler/TaskScenario.rb
@@ -1508,6 +1508,7 @@ class TaskJuggler
             end
             q = query.dup
             q.property = resource
+            q.scopeProperty = @property
             rti.setQuery(q)
             list << "<nowiki>#{rti.to_s}</nowiki>"
           else
@@ -2179,8 +2180,12 @@ class TaskJuggler
       # been set already.
       if @scheduled && @effort == 0 && @length == 0 && @duration == 0 &&
          !@milestone
-        @start = @project.idxToDate(firstSlotIdx) unless @start
-        @end = @project.idxToDate(lastSlotIdx + 1) unless @end
+        unless @start || !firstSlotIdx
+          @start = @project.idxToDate(firstSlotIdx)
+        end
+        unless @end || !lastSlotIdx
+          @end = @project.idxToDate(lastSlotIdx + 1)
+        end
       end
     end
 
diff --git a/lib/taskjuggler/TimeSheets.rb b/lib/taskjuggler/TimeSheets.rb
index 8faf6da7..91ecd699 100644
--- a/lib/taskjuggler/TimeSheets.rb
+++ b/lib/taskjuggler/TimeSheets.rb
@@ -325,9 +325,10 @@ class TaskJuggler
     def totalGrossWorkingSlots
       project = @resource.project
       # Calculate the number of weeks in the report
-      weeksToReport = (@interval.end - @interval.start) / (60 * 60 * 24 * 7)
+      weeksToReport = (@interval.end - @interval.start).to_f /
+        (60 * 60 * 24 * 7)
 
-      daysToSlots(project.weeklyWorkingDays * weeksToReport)
+      daysToSlots((project.weeklyWorkingDays * weeksToReport).to_i)
     end
 
     # Compute the total number of actual working time slots of the
diff --git a/lib/taskjuggler/TjpSyntaxRules.rb b/lib/taskjuggler/TjpSyntaxRules.rb
index 25a112f0..74f2a347 100644
--- a/lib/taskjuggler/TjpSyntaxRules.rb
+++ b/lib/taskjuggler/TjpSyntaxRules.rb
@@ -3,7 +3,7 @@
 #
 # = TjpSyntaxRules.rb -- The TaskJuggler III Project Management Software
 #
-# Copyright (c) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014
+# Copyright (c) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2020
 #               by Chris Schlaeger <cs@taskjuggler.org>
 #
 # This program is free software; you can redistribute it and/or modify
@@ -3932,7 +3932,13 @@ EOT
     descr('The duration of a task')
 
     singlePattern('_duties')
-    descr('List of tasks that the resource is allocated to')
+    descr(<<'EOT'
+List of tasks that the resource is allocated to
+
+The list can be customized by the [[listitem.column|listitem]] and
+[[listtype.column|listtype]] attribute.
+EOT
+         )
 
     singlePattern('_efficiency')
     descr('Measure for how efficient a resource can perform tasks')
diff --git a/lib/taskjuggler/reports/CSVFile.rb b/lib/taskjuggler/reports/CSVFile.rb
index 0ee08d15..46edfa7e 100644
--- a/lib/taskjuggler/reports/CSVFile.rb
+++ b/lib/taskjuggler/reports/CSVFile.rb
@@ -221,7 +221,7 @@ class TaskJuggler
         field.to_s
       else
         # Duplicate quote characters.
-        f = field.gsub(/@quote/, "#{@quote * 2}")
+        f = field.gsub(Regexp.new(@quote), "#{@quote * 2}")
         # Enclose the field in quote characters
         @quote + f.to_s + @quote
       end
diff --git a/test/TestSuite/CSV-Reports/quotes.tjp b/test/TestSuite/CSV-Reports/quotes.tjp
new file mode 100644
index 00000000..4d8c26f9
--- /dev/null
+++ b/test/TestSuite/CSV-Reports/quotes.tjp
@@ -0,0 +1,20 @@
+project "targets" "1.0" 2007-12-16 +3m {
+  timezone 'UTC'
+}
+
+task t1 "T1"
+task t2 "T2" {
+  depends !t1
+}
+task t3 "T3" {
+  depends !t1
+}
+task t4 "T4 with \"quotes\"" {
+  depends !t3
+}
+
+taskreport '.' {
+  formats csv
+  columns name, targets
+}
+
diff --git a/test/TestSuite/CSV-Reports/refs/quotes.csv b/test/TestSuite/CSV-Reports/refs/quotes.csv
new file mode 100644
index 00000000..54e1d7b8
--- /dev/null
+++ b/test/TestSuite/CSV-Reports/refs/quotes.csv
@@ -0,0 +1,5 @@
+"Name";"Targets"
+"T1";"T2 (t2) 2007-12-16, T4 with ""quotes"" (t4) 2007-12-16"
+"T2";""
+"T3";"T4 with ""quotes"" (t4) 2007-12-16"
+"T4 with ""quotes""";""

Branch: pristine-tar

diff --git a/tj3_3.7.1+git20200830.1.8198281.orig.tar.gz.delta b/tj3_3.7.1+git20200830.1.8198281.orig.tar.gz.delta
new file mode 100644
index 00000000..22b30dbc
Binary files /dev/null and b/tj3_3.7.1+git20200830.1.8198281.orig.tar.gz.delta differ
diff --git a/tj3_3.7.1+git20200830.1.8198281.orig.tar.gz.id b/tj3_3.7.1+git20200830.1.8198281.orig.tar.gz.id
new file mode 100644
index 00000000..bf6071b5
--- /dev/null
+++ b/tj3_3.7.1+git20200830.1.8198281.orig.tar.gz.id
@@ -0,0 +1 @@
+814c0ce341df329f0a96f5d9897e4cf5b755a877

Branch: upstream

Tag: upstream/3.7.1+git20200830.1.8198281
diff --git a/lib/taskjuggler/ResourceScenario.rb b/lib/taskjuggler/ResourceScenario.rb
index c6388ae2..b45e749e 100644
--- a/lib/taskjuggler/ResourceScenario.rb
+++ b/lib/taskjuggler/ResourceScenario.rb
@@ -3,7 +3,7 @@
 #
 # = ResourceScenario.rb -- The TaskJuggler III Project Management Software
 #
-# Copyright (c) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014
+# Copyright (c) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2020
 #               by Chris Schlaeger <cs@taskjuggler.org>
 #
 # This program is free software; you can redistribute it and/or modify
@@ -322,6 +322,34 @@ class TaskJuggler
       end
     end
 
+    # A list of the tasks that the resource has been  allocated to work on in
+    # the report time frame.
+    def query_duties(query)
+      list = []
+      iv = TimeInterval.new(query.start, query.end)
+      @duties.each do |task|
+        if task.hasResourceAllocated?(@scenarioIdx, iv, @property)
+          if query.listItem
+            rti = RichText.new(query.listItem, RTFHandlers.create(@project)).
+              generateIntermediateFormat
+            unless rti
+              error('bad_resource_ts_query',
+                    "Syntax error in query statement for task attribute " +
+                    "'resources'.")
+            end
+            q = query.dup
+            q.property = task
+            q.scopeProperty = @property
+            rti.setQuery(q)
+            list << "<nowiki>#{rti.to_s}</nowiki>"
+          else
+            list << "<nowiki>#{task.name} (#{task.id})</nowiki>"
+          end
+        end
+      end
+      query.assignList(list)
+    end
+
     # The effort allocated to the Resource in the specified interval. In case a
     # Task is given as scope property only the effort allocated to this Task is
     # taken into account.
diff --git a/lib/taskjuggler/RuntimeConfig.rb b/lib/taskjuggler/RuntimeConfig.rb
index 386b46d7..d6dd1636 100644
--- a/lib/taskjuggler/RuntimeConfig.rb
+++ b/lib/taskjuggler/RuntimeConfig.rb
@@ -48,7 +48,7 @@ class RuntimeConfig
     return false unless (p = @config)
     sections.each do |sec|
       p = p['_' + sec]
-      unless p
+      unless p && p.is_a?(Hash)
         debug("Section #{section} not found in config file")
         return false
       end
diff --git a/lib/taskjuggler/TaskScenario.rb b/lib/taskjuggler/TaskScenario.rb
index d54b2d4c..392d68df 100644
--- a/lib/taskjuggler/TaskScenario.rb
+++ b/lib/taskjuggler/TaskScenario.rb
@@ -1508,6 +1508,7 @@ class TaskJuggler
             end
             q = query.dup
             q.property = resource
+            q.scopeProperty = @property
             rti.setQuery(q)
             list << "<nowiki>#{rti.to_s}</nowiki>"
           else
@@ -2179,8 +2180,12 @@ class TaskJuggler
       # been set already.
       if @scheduled && @effort == 0 && @length == 0 && @duration == 0 &&
          !@milestone
-        @start = @project.idxToDate(firstSlotIdx) unless @start
-        @end = @project.idxToDate(lastSlotIdx + 1) unless @end
+        unless @start || !firstSlotIdx
+          @start = @project.idxToDate(firstSlotIdx)
+        end
+        unless @end || !lastSlotIdx
+          @end = @project.idxToDate(lastSlotIdx + 1)
+        end
       end
     end
 
diff --git a/lib/taskjuggler/TimeSheets.rb b/lib/taskjuggler/TimeSheets.rb
index 8faf6da7..91ecd699 100644
--- a/lib/taskjuggler/TimeSheets.rb
+++ b/lib/taskjuggler/TimeSheets.rb
@@ -325,9 +325,10 @@ class TaskJuggler
     def totalGrossWorkingSlots
       project = @resource.project
       # Calculate the number of weeks in the report
-      weeksToReport = (@interval.end - @interval.start) / (60 * 60 * 24 * 7)
+      weeksToReport = (@interval.end - @interval.start).to_f /
+        (60 * 60 * 24 * 7)
 
-      daysToSlots(project.weeklyWorkingDays * weeksToReport)
+      daysToSlots((project.weeklyWorkingDays * weeksToReport).to_i)
     end
 
     # Compute the total number of actual working time slots of the
diff --git a/lib/taskjuggler/TjpSyntaxRules.rb b/lib/taskjuggler/TjpSyntaxRules.rb
index 25a112f0..74f2a347 100644
--- a/lib/taskjuggler/TjpSyntaxRules.rb
+++ b/lib/taskjuggler/TjpSyntaxRules.rb
@@ -3,7 +3,7 @@
 #
 # = TjpSyntaxRules.rb -- The TaskJuggler III Project Management Software
 #
-# Copyright (c) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014
+# Copyright (c) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2020
 #               by Chris Schlaeger <cs@taskjuggler.org>
 #
 # This program is free software; you can redistribute it and/or modify
@@ -3932,7 +3932,13 @@ EOT
     descr('The duration of a task')
 
     singlePattern('_duties')
-    descr('List of tasks that the resource is allocated to')
+    descr(<<'EOT'
+List of tasks that the resource is allocated to
+
+The list can be customized by the [[listitem.column|listitem]] and
+[[listtype.column|listtype]] attribute.
+EOT
+         )
 
     singlePattern('_efficiency')
     descr('Measure for how efficient a resource can perform tasks')
diff --git a/lib/taskjuggler/reports/CSVFile.rb b/lib/taskjuggler/reports/CSVFile.rb
index 0ee08d15..46edfa7e 100644
--- a/lib/taskjuggler/reports/CSVFile.rb
+++ b/lib/taskjuggler/reports/CSVFile.rb
@@ -221,7 +221,7 @@ class TaskJuggler
         field.to_s
       else
         # Duplicate quote characters.
-        f = field.gsub(/@quote/, "#{@quote * 2}")
+        f = field.gsub(Regexp.new(@quote), "#{@quote * 2}")
         # Enclose the field in quote characters
         @quote + f.to_s + @quote
       end
diff --git a/test/TestSuite/CSV-Reports/quotes.tjp b/test/TestSuite/CSV-Reports/quotes.tjp
new file mode 100644
index 00000000..4d8c26f9
--- /dev/null
+++ b/test/TestSuite/CSV-Reports/quotes.tjp
@@ -0,0 +1,20 @@
+project "targets" "1.0" 2007-12-16 +3m {
+  timezone 'UTC'
+}
+
+task t1 "T1"
+task t2 "T2" {
+  depends !t1
+}
+task t3 "T3" {
+  depends !t1
+}
+task t4 "T4 with \"quotes\"" {
+  depends !t3
+}
+
+taskreport '.' {
+  formats csv
+  columns name, targets
+}
+
diff --git a/test/TestSuite/CSV-Reports/refs/quotes.csv b/test/TestSuite/CSV-Reports/refs/quotes.csv
new file mode 100644
index 00000000..54e1d7b8
--- /dev/null
+++ b/test/TestSuite/CSV-Reports/refs/quotes.csv
@@ -0,0 +1,5 @@
+"Name";"Targets"
+"T1";"T2 (t2) 2007-12-16, T4 with ""quotes"" (t4) 2007-12-16"
+"T2";""
+"T3";"T4 with ""quotes"" (t4) 2007-12-16"
+"T4 with ""quotes""";""

Debdiff

File lists identical (after any substitutions)

No differences were encountered between the control files of package tj3

No differences were encountered between the control files of package vim-tjp

Resulting package

The resulting binary packages can be installed (if you have the apt repository enabled) by running one of:

apt install -t fresh-snapshots tj3
apt install -t fresh-snapshots vim-tjp

Lintian Result

Full worker log Full build log Full dist log