tractive 1.0.5 → 1.0.9

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: db1fec86bca93ac81ac4ce8c4f1e6fb99f0983743c55fc3275a95188c8178e0e
4
- data.tar.gz: f2907430c9a64b4cd5e0004050c1d7eddf11a18f94a4a007bf5315706a73e23b
3
+ metadata.gz: 5ebcddc1621be979b25f4041cc4eac2429e6a6a08b05611154c230d49d9de86c
4
+ data.tar.gz: f61bd5af4741266ae56d81c277c7aaec723a49358f81dcb6eebdc3dbaae2e37c
5
5
  SHA512:
6
- metadata.gz: 1828a51469e9418188cd72195b51b245bb47921b7fbc883287bd089f9b2da58d18fbf08411c9f5cc33ed4a4a92259e365931afe281e1cf810a16c97a0632fa1a
7
- data.tar.gz: f898f265b58c41ca3ae59ee20cf52ec50ced92045a1595f23ea50e66bb4b0bd911a8695cfdc34b3a41a248a8b11bcb3a20be70eb8193aba8a7867c3f9ba4cc1e
6
+ metadata.gz: b29d97cc67c43cc4d9ee72d88563e01dc6d7cdc7b988ed3b987c73a3cbc9a2fc8746597c3d3b1e175ebca83073fd6e4b19f8b51f60c9792849893a6816483f5d
7
+ data.tar.gz: d07192c1b845a3a4ca266e881ead6a7583ba5575313d68372ffa9df6785c0f4e8856be09cafdf736bb279e5e651a4d3eb1e6f294b0754b0dd4c3a5dfded9ac03
data/.gitignore CHANGED
@@ -9,3 +9,4 @@
9
9
 
10
10
  # rspec failure tracking
11
11
  .rspec_status
12
+ Gemfile.lock
data/.rubocop.yml CHANGED
@@ -25,12 +25,18 @@ Style/Documentation:
25
25
  Style/GlobalVars:
26
26
  Enabled: false
27
27
 
28
+ Style/HashTransformKeys:
29
+ Enabled: false
30
+
28
31
  Metrics/AbcSize:
29
32
  Enabled: false
30
33
 
31
34
  Metrics/MethodLength:
32
35
  Enabled: false
33
36
 
37
+ Metrics/ModuleLength:
38
+ Max: 150
39
+
34
40
  Security/Open:
35
41
  Enabled: false
36
42
 
data/README.adoc CHANGED
@@ -297,6 +297,8 @@ trac:
297
297
  ticketbaseurl: https://example.org/trac/foobar/ticket
298
298
  ----
299
299
 
300
+ `ticketbaseurl:`::: The Trac Url which will be added in Github issues. A link will be added in the footer of Github issue to link it to Trac ticket.
301
+
300
302
  [[config-github]]
301
303
  ==== GitHub configuration
302
304
 
@@ -680,6 +682,7 @@ The following options are allowed (at least one necessary):
680
682
  * `column-name`
681
683
  * `operator`
682
684
  * `column-value`
685
+ * `include-null`
683
686
 
684
687
  | Boolean
685
688
 
@@ -695,6 +698,10 @@ The following options are allowed (at least one necessary):
695
698
  | Value of the column to filter.
696
699
  | String
697
700
 
701
+ | `--include-null`
702
+ | Include rows having null value in filtered column.
703
+ | Boolean
704
+
698
705
  | `-h`, `help`
699
706
  | Display the Tractive help message, or you can provide a command to know more
700
707
  about a single command via `tractive help {command}`.
data/db/trac-test.db CHANGED
Binary file
data/exe/tractive CHANGED
@@ -30,6 +30,8 @@ class TractiveCommand < Thor
30
30
  desc: "Operator for filter."
31
31
  method_option "columnvalue", type: :string, aliases: ["--column-value"],
32
32
  desc: "Value of the column to filter."
33
+ method_option "includenull", type: :boolean, aliases: ["--include-null"],
34
+ desc: "Flag for including null values in the filter result."
33
35
 
34
36
  method_option "importfromfile", type: :string, aliases: ["-I", "--import-from-file"],
35
37
  desc: "Import issues from a json file"
data/lib/tractive/info.rb CHANGED
@@ -34,8 +34,8 @@ module Tractive
34
34
  "milestones" => milestones,
35
35
  "labels" => {
36
36
  "type" => Utilities.make_hash("type_", types),
37
- "component" => Utilities.make_hash("component_", components),
38
37
  "resolution" => Utilities.make_hash("resolution_", resolutions),
38
+ "component" => Utilities.make_each_hash(components, %w[name color], "component: "),
39
39
  "severity" => Utilities.make_each_hash(severity, %w[name color]),
40
40
  "priority" => Utilities.make_each_hash(priorities, %w[name color]),
41
41
  "tracstate" => Utilities.make_each_hash(tracstates, %w[name color])
data/lib/tractive/main.rb CHANGED
@@ -8,7 +8,7 @@ module Tractive
8
8
  @opts = opts
9
9
  @cfg = YAML.load_file(@opts[:config])
10
10
 
11
- Tractive::Utilities.setup_logger(output_stream: @opts[:log_file] || $stderr, verbose: @opts[:verbose])
11
+ Tractive::Utilities.setup_logger(output_stream: @opts[:logfile] || $stderr, verbose: @opts[:verbose])
12
12
  @db = Tractive::Utilities.setup_db!(@cfg["trac"]["database"])
13
13
  rescue Sequel::DatabaseConnectionError, Sequel::AdapterNotFound, URI::InvalidURIError, Sequel::DatabaseError => e
14
14
  $logger.error e.message
@@ -6,7 +6,7 @@ module Migrator
6
6
  def initialize(args)
7
7
  @tracticketbaseurl = args[:cfg]["trac"]["ticketbaseurl"]
8
8
  @attachurl = args[:opts][:attachurl] || args[:cfg].dig("attachments", "url")
9
- @changeset_base_url = args[:cfg]["trac"]["changeset_base_url"]
9
+ @changeset_base_url = args[:cfg]["trac"]["changeset_base_url"] || ""
10
10
  @singlepost = args[:opts][:singlepost]
11
11
  @labels_cfg = args[:cfg]["labels"].transform_values(&:to_h)
12
12
  @milestonesfromtrac = args[:cfg]["milestones"]
@@ -15,14 +15,17 @@ module Migrator
15
15
  @repo = args[:cfg]["github"]["repo"]
16
16
  @client = GithubApi::Client.new(access_token: args[:cfg]["github"]["token"])
17
17
  @wiki_attachments_url = args[:cfg]["trac"]["wiki_attachments_url"]
18
+ @revmap_file_path = args[:opts][:revmapfile] || args[:cfg]["revmap_path"]
19
+ @attachment_options = { hashed: args[:cfg].dig("attachments", "hashed") }
18
20
 
19
21
  load_milestone_map
20
22
  create_labels_on_github(@labels_cfg["severity"].values)
21
23
  create_labels_on_github(@labels_cfg["priority"].values)
22
24
  create_labels_on_github(@labels_cfg["tracstate"].values)
25
+ create_labels_on_github(@labels_cfg["component"].values)
23
26
 
24
27
  @uri_parser = URI::Parser.new
25
- @twf_to_markdown = Migrator::Converter::TwfToMarkdown.new(@tracticketbaseurl, @attachurl, @changeset_base_url, @wiki_attachments_url)
28
+ @twf_to_markdown = Migrator::Converter::TwfToMarkdown.new(@tracticketbaseurl, @attachurl, @changeset_base_url, @wiki_attachments_url, @revmap_file_path)
26
29
  end
27
30
 
28
31
  def compose(ticket)
@@ -77,7 +80,6 @@ module Migrator
77
80
 
78
81
  badges = Set[]
79
82
 
80
- badges.add(@labels_cfg.fetch("component", {})[ticket[:component]])
81
83
  badges.add(@labels_cfg.fetch("type", {})[ticket[:type]])
82
84
  badges.add(@labels_cfg.fetch("resolution", {})[ticket[:resolution]])
83
85
  badges.add(@labels_cfg.fetch("version", {})[ticket[:version]])
@@ -85,6 +87,8 @@ module Migrator
85
87
  labels.add(@labels_cfg.fetch("severity", {})[ticket[:severity]])
86
88
  labels.add(@labels_cfg.fetch("priority", {})[ticket[:priority]])
87
89
  labels.add(@labels_cfg.fetch("tracstate", {})[ticket[:status]])
90
+ labels.add(@labels_cfg.fetch("component", {})[ticket[:component]])
91
+
88
92
  labels.delete(nil)
89
93
 
90
94
  keywords = ticket[:keywords]
@@ -100,7 +104,7 @@ module Migrator
100
104
  milestone = @milestonemap[ticket[:milestone]]
101
105
 
102
106
  # compute footer
103
- footer = "_Issue migrated from trac:#{ticket[:id]} at #{Time.now}_"
107
+ footer = "_Issue migrated from #{trac_ticket_link(ticket)} at #{Time.now}_"
104
108
 
105
109
  # compute badgetabe
106
110
  #
@@ -201,8 +205,17 @@ module Migrator
201
205
  def create_labels_on_github(labels)
202
206
  return if labels.nil? || labels.empty?
203
207
 
204
- existing_labels = @client.labels(@repo, per_page: 100).map { |label| label["name"] }
205
- new_labels = labels.reject { |label| existing_labels.include?(label["name"]) }
208
+ page = 1
209
+ existing_labels = []
210
+ result = @client.labels(@repo, per_page: 100, page: page).map { |label| label["name"] }
211
+
212
+ until result.empty?
213
+ existing_labels += result
214
+ page += 1
215
+ result = @client.labels(@repo, per_page: 100, page: page).map { |label| label["name"] }
216
+ end
217
+
218
+ new_labels = labels.reject { |label| existing_labels.include?(label["name"]&.strip) }
206
219
 
207
220
  new_labels.each do |label|
208
221
  params = { name: label["name"] }
@@ -262,7 +275,7 @@ module Migrator
262
275
  changeset = body.match(/In \[changeset:"(\d+)/).to_a[1]
263
276
  text += if changeset
264
277
  # changesethash = @revmap[changeset]
265
- "_committed #{Tractive::Utilities.map_changeset(changeset)}_"
278
+ "_committed #{Tractive::Utilities.map_changeset(changeset, @revmap, @changeset_base_url)}_"
266
279
  else
267
280
  "_commented_\n\n"
268
281
  end
@@ -275,7 +288,7 @@ module Migrator
275
288
  name = meta[:filename]
276
289
  body = meta[:description]
277
290
  if @attachurl
278
- url = @uri_parser.escape("#{@attachurl}/#{meta[:id]}/#{name}")
291
+ url = @uri_parser.escape("#{@attachurl}/#{attachment_path(meta[:id], name, @attachment_options)}")
279
292
  text += "[`#{name}`](#{url})"
280
293
  body += "\n![#{name}](#{url})" if [".png", ".jpg", ".gif"].include? File.extname(name).downcase
281
294
  else
@@ -321,6 +334,23 @@ module Migrator
321
334
  !(%w[keywords cc reporter version].include?(kind) ||
322
335
  (kind == "comment" && (newvalue.nil? || newvalue.lstrip.empty?)))
323
336
  end
337
+
338
+ def trac_ticket_link(ticket)
339
+ return "trac:#{ticket[:id]}" unless @tracticketbaseurl
340
+
341
+ "[trac:#{ticket[:id]}](#{@tracticketbaseurl}/#{ticket[:id]})"
342
+ end
343
+
344
+ def attachment_path(id, filename, options = {})
345
+ return "#{id}/#{filename}" unless options[:hashed]
346
+
347
+ folder_name = Digest::SHA1.hexdigest(id)
348
+ parent_folder_name = folder_name[0..2]
349
+ hashed_filename = Digest::SHA1.hexdigest(filename)
350
+ file_extension = File.extname(filename)
351
+
352
+ "#{parent_folder_name}/#{folder_name}/#{hashed_filename}#{file_extension}"
353
+ end
324
354
  end
325
355
  end
326
356
  end
@@ -4,11 +4,12 @@ module Migrator
4
4
  module Converter
5
5
  # twf => Trac wiki format
6
6
  class TwfToMarkdown
7
- def initialize(base_url, attach_url, changeset_base_url, wiki_attachments_url)
7
+ def initialize(base_url, attach_url, changeset_base_url, wiki_attachments_url, revmap_file_path)
8
8
  @base_url = base_url
9
9
  @attach_url = attach_url
10
10
  @changeset_base_url = changeset_base_url
11
11
  @wiki_attachments_url = wiki_attachments_url
12
+ @revmap = load_revmap_file(revmap_file_path)
12
13
  end
13
14
 
14
15
  def convert(str)
@@ -26,6 +27,24 @@ module Migrator
26
27
 
27
28
  private
28
29
 
30
+ def load_revmap_file(revmapfile)
31
+ # load revision mapping file and convert it to a hash.
32
+ # This revmap file allows to map between SVN revisions (rXXXX)
33
+ # and git commit sha1 hashes.
34
+ revmap = nil
35
+ if revmapfile
36
+ File.open(revmapfile, "r:UTF-8") do |f|
37
+ $logger.info("loading revision map #{revmapfile}")
38
+
39
+ revmap = f.each_line
40
+ .map { |line| line.split(/\s+\|\s+/) }
41
+ .map { |rev, sha| [rev.gsub(/^r/, ""), sha] }.to_h # remove leading "r" if present
42
+ end
43
+ end
44
+
45
+ revmap
46
+ end
47
+
29
48
  # CommitTicketReference
30
49
  def convert_ticket_reference(str)
31
50
  str.gsub!(/\{\{\{\n(#!CommitTicketReference .+?)\}\}\}/m, '\1')
@@ -72,9 +91,11 @@ module Migrator
72
91
  str.gsub!(%r{#{Regexp.quote(changeset_base_url)}/(\d+)/?}, '[changeset:\1]') if changeset_base_url
73
92
  str.gsub!(/\[changeset:"r(\d+)".*\]/, '[changeset:\1]')
74
93
  str.gsub!(/\[changeset:r(\d+)\]/, '[changeset:\1]')
75
- str.gsub!(/\br(\d+)\b/) { Tractive::Utilities.map_changeset(Regexp.last_match[1]) }
76
- str.gsub!(/\[changeset:"(\d+)".*\]/) { Tractive::Utilities.map_changeset(Regexp.last_match[1]) }
77
- str.gsub!(/\[changeset:"(\d+).*\]/) { Tractive::Utilities.map_changeset(Regexp.last_match[1]) }
94
+ str.gsub!(/\br(\d+)\b/) { Tractive::Utilities.map_changeset(Regexp.last_match[1], @revmap, changeset_base_url) }
95
+ str.gsub!(/\[changeset:"(\d+)".*\]/) { Tractive::Utilities.map_changeset(Regexp.last_match[1], @revmap, changeset_base_url) }
96
+ str.gsub!(/\[changeset:(\d+).*\]/) { Tractive::Utilities.map_changeset(Regexp.last_match[1], @revmap, changeset_base_url) }
97
+ str.gsub!(/\[(\d+)\]/) { Tractive::Utilities.map_changeset(Regexp.last_match[1], @revmap, changeset_base_url) }
98
+ str.gsub!(%r{\[(\d+)/.*\]}) { Tractive::Utilities.map_changeset(Regexp.last_match[1], @revmap, changeset_base_url) }
78
99
  end
79
100
 
80
101
  # Font styles
@@ -27,7 +27,7 @@ module Migrator
27
27
  input_file_name = args[:opts][:importfromfile]
28
28
 
29
29
  @filter_applied = args[:opts][:filter]
30
- @filter_options = { column_name: args[:opts][:columnname], operator: args[:opts][:operator], column_value: args[:opts][:columnvalue] }
30
+ @filter_options = { column_name: args[:opts][:columnname], operator: args[:opts][:operator], column_value: args[:opts][:columnvalue], include_null: args[:opts][:includenull] }
31
31
 
32
32
  @trac = Tractive::Trac.new(db)
33
33
  @repo = github["repo"]
@@ -87,7 +87,7 @@ module Migrator
87
87
 
88
88
  revmap = f.each_line
89
89
  .map { |line| line.split(/\s+\|\s+/) }
90
- .map { |rev, sha, _| [rev.gsub(/^r/, ""), sha] }.to_h # remove leading "r" if present
90
+ .map { |rev, sha| [rev.gsub(/^r/, ""), sha] }.to_h # remove leading "r" if present
91
91
  end
92
92
  end
93
93
 
@@ -19,14 +19,18 @@ module Tractive
19
19
  def filter_column(options)
20
20
  return self if options.nil? || options.values.compact.empty?
21
21
 
22
- case options[:operator].downcase
23
- when "like"
24
- where { Sequel.like(options[:column_name].to_sym, options[:column_value]) }
25
- when "not like"
26
- where { ~Sequel.like(options[:column_name].to_sym, options[:column_value]) }
27
- else
28
- where { Sequel.lit("#{options[:column_name]} #{options[:operator]} '#{options[:column_value]}'") }
29
- end
22
+ query = case options[:operator].downcase
23
+ when "like"
24
+ Sequel.like(options[:column_name].to_sym, options[:column_value])
25
+ when "not like"
26
+ ~Sequel.like(options[:column_name].to_sym, options[:column_value])
27
+ else
28
+ Sequel.lit("#{options[:column_name]} #{options[:operator]} '#{options[:column_value]}'")
29
+ end
30
+
31
+ query = Sequel.|(query, { options[:column_name].to_sym => nil }) if options[:include_null]
32
+
33
+ where { query }
30
34
  end
31
35
  end
32
36
 
@@ -7,10 +7,10 @@ module Tractive
7
7
  array.map { |i| [i, "#{prefix}#{i}"] }.to_h
8
8
  end
9
9
 
10
- def make_each_hash(values, keys)
10
+ def make_each_hash(values, keys, prefix = "")
11
11
  values.map do |value|
12
12
  value = [value] unless value.is_a?(Array)
13
- [value[0], keys.zip(value).to_h]
13
+ [value[0], keys.zip(value.map { |v| "#{prefix}#{v}" }).to_h]
14
14
  end.to_h
15
15
  end
16
16
 
@@ -45,11 +45,13 @@ module Tractive
45
45
  end
46
46
 
47
47
  # returns the git commit hash for a specified revision (using revmap hash)
48
- def map_changeset(str)
49
- if @revmap&.key?(str)
50
- "[r#{str}](../commit/#{@revmap[str]}) #{@revmap[str]}"
48
+ def map_changeset(str, revmap, changeset_base_url = "")
49
+ if revmap&.key?(str)
50
+ base_url = changeset_base_url
51
+ base_url += "/" if base_url[-1] && base_url[-1] != "/"
52
+ "#{base_url}#{revmap[str].strip}"
51
53
  else
52
- str
54
+ "[#{str}]"
53
55
  end
54
56
  end
55
57
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Tractive
4
- VERSION = "1.0.5"
4
+ VERSION = "1.0.9"
5
5
  end
data/tractive.gemspec CHANGED
@@ -16,6 +16,7 @@ Gem::Specification.new do |spec|
16
16
  spec.metadata["homepage_uri"] = spec.homepage
17
17
  spec.metadata["source_code_uri"] = "https://github.com/ietf-ribose/tractive"
18
18
  spec.metadata["changelog_uri"] = "https://github.com/ietf-ribose/tractive"
19
+ spec.metadata["rubygems_mfa_required"] = "true"
19
20
 
20
21
  # Specify which files should be added to the gem when it is released.
21
22
  # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tractive
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.5
4
+ version: 1.0.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-10-21 00:00:00.000000000 Z
11
+ date: 2021-12-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: mysql2
@@ -124,7 +124,6 @@ files:
124
124
  - ".ruby-version"
125
125
  - CODE_OF_CONDUCT.md
126
126
  - Gemfile
127
- - Gemfile.lock
128
127
  - LICENSE.md
129
128
  - README.adoc
130
129
  - Rakefile
@@ -171,6 +170,7 @@ metadata:
171
170
  homepage_uri: https://github.com/ietf-ribose/tractive
172
171
  source_code_uri: https://github.com/ietf-ribose/tractive
173
172
  changelog_uri: https://github.com/ietf-ribose/tractive
173
+ rubygems_mfa_required: 'true'
174
174
  post_install_message:
175
175
  rdoc_options: []
176
176
  require_paths:
data/Gemfile.lock DELETED
@@ -1,100 +0,0 @@
1
- PATH
2
- remote: .
3
- specs:
4
- tractive (1.0.5)
5
- mysql2
6
- ox
7
- rest-client
8
- sequel
9
- sqlite3
10
- thor
11
-
12
- GEM
13
- remote: https://rubygems.org/
14
- specs:
15
- addressable (2.8.0)
16
- public_suffix (>= 2.0.2, < 5.0)
17
- ast (2.4.2)
18
- coderay (1.1.3)
19
- crack (0.4.5)
20
- rexml
21
- diff-lcs (1.4.4)
22
- domain_name (0.5.20190701)
23
- unf (>= 0.0.5, < 1.0.0)
24
- hashdiff (1.0.1)
25
- http-accept (1.7.0)
26
- http-cookie (1.0.4)
27
- domain_name (~> 0.5)
28
- method_source (1.0.0)
29
- mime-types (3.3.1)
30
- mime-types-data (~> 3.2015)
31
- mime-types-data (3.2021.0901)
32
- mysql2 (0.5.3)
33
- netrc (0.11.0)
34
- ox (2.14.5)
35
- parallel (1.21.0)
36
- parser (3.0.2.0)
37
- ast (~> 2.4.1)
38
- pry (0.14.1)
39
- coderay (~> 1.1)
40
- method_source (~> 1.0)
41
- public_suffix (4.0.6)
42
- rainbow (3.0.0)
43
- rake (13.0.6)
44
- regexp_parser (2.1.1)
45
- rest-client (2.1.0)
46
- http-accept (>= 1.7.0, < 2.0)
47
- http-cookie (>= 1.0.2, < 2.0)
48
- mime-types (>= 1.16, < 4.0)
49
- netrc (~> 0.8)
50
- rexml (3.2.5)
51
- rspec (3.10.0)
52
- rspec-core (~> 3.10.0)
53
- rspec-expectations (~> 3.10.0)
54
- rspec-mocks (~> 3.10.0)
55
- rspec-core (3.10.1)
56
- rspec-support (~> 3.10.0)
57
- rspec-expectations (3.10.1)
58
- diff-lcs (>= 1.2.0, < 2.0)
59
- rspec-support (~> 3.10.0)
60
- rspec-mocks (3.10.2)
61
- diff-lcs (>= 1.2.0, < 2.0)
62
- rspec-support (~> 3.10.0)
63
- rspec-support (3.10.2)
64
- rubocop (1.22.1)
65
- parallel (~> 1.10)
66
- parser (>= 3.0.0.0)
67
- rainbow (>= 2.2.2, < 4.0)
68
- regexp_parser (>= 1.8, < 3.0)
69
- rexml
70
- rubocop-ast (>= 1.12.0, < 2.0)
71
- ruby-progressbar (~> 1.7)
72
- unicode-display_width (>= 1.4.0, < 3.0)
73
- rubocop-ast (1.12.0)
74
- parser (>= 3.0.1.1)
75
- ruby-progressbar (1.11.0)
76
- sequel (5.49.0)
77
- sqlite3 (1.4.2)
78
- thor (1.1.0)
79
- unf (0.1.4)
80
- unf_ext
81
- unf_ext (0.0.8)
82
- unicode-display_width (2.1.0)
83
- webmock (3.14.0)
84
- addressable (>= 2.8.0)
85
- crack (>= 0.3.2)
86
- hashdiff (>= 0.4.0, < 2.0.0)
87
-
88
- PLATFORMS
89
- ruby
90
-
91
- DEPENDENCIES
92
- pry
93
- rake (~> 13.0)
94
- rspec (~> 3.0)
95
- rubocop (~> 1.7)
96
- tractive!
97
- webmock (~> 3.14)
98
-
99
- BUNDLED WITH
100
- 2.1.2